web-dev-qa-db-ja.com

Java 11ランタイムがSun.miscクラスを含むjarを無視するのはなぜですか?

コードベースをJava 11にアップグレードしようとしています。残念ながら、私のコードはSun.misc.BASE64EncoderおよびDecoderを内部で使用するサードパーティライブラリに依存しています。 Sun.miscパッケージがJava 11 JREから削除されているため、失敗しています。そのライブラリの所有者はまだその依存関係を置き換えていないため、ながら。

コードを制御できる場合は、Java.util.BASE64クラスを使用しますが、前述のとおり、これらは別のライブラリからの推移的な依存関係として発生しているため、変更できません。

私は賢く、それらのクラスだけで新しいjarを作成すると思いましたが、何らかの理由でそのjarは無視されています。

enter image description here

<dependency>
    <groupId>Sun.misc</groupId>
    <artifactId>BASE64</artifactId>
    <version>1.8</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/Sun.jar</systemPath>
</dependency>

また、明示的にクラスパスに追加しようとしましたが、まだうまくいきませんでした

これは、JREが操作を妨げているパッケージの1つですか、それとも一部のモジュール仕様がないのですか、それともショーストッパーですか?

これが出力です

Java.lang.NoClassDefFoundError: Sun/misc/BASE64Encoder
at com.propsco.util.support.PropsLoader.save(PropsLoader.Java:478) ~[props-client-2.2.1.jar:na]
10
Vinny Gray

この回答は、

> Java --version
openjdk 11.0.3 2019-04-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.3+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.3+7, mixed mode)

最初に、BASE64Encoderをオーバーライドするプロジェクトを作成します。それをSun-misc-overrideと呼びましょう。 src\main\Javaの下に、Sun.miscクラスを含むBASE64Encoderパッケージを作成します。

package Sun.misc;

public class BASE64Encoder {
    public String encode(byte[] aBuffer) {
        return "Fake it until you make it!";
    }
}

コンパイルしようとすると、Sun\misc\BASE64Encoder.Java:1: error: package exists in another module: jdk.unsupportedエラーが発生します。

これにより、 パッチモジュールjdk.unsupportedに必要なヒントが得られます。これは、元のSun.miscパッケージのクラスが、モジュールシステムがJava 9でロールアウトされた後、時間の経過とともに削除されたときにjdk.unsupportedモジュールに移動されたためです(参照 JEP-260 )。

Mavenでは、コンパイラプラグインを次のように設定できます。

<plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <release>11</release>
        <compilerArgs>
            <arg>--patch-module</arg>
            <arg>jdk.unsupported=${project.basedir}/src/main/Java</arg>
        </compilerArgs>
    </configuration>
</plugin>

com.example:Sun-misc-override:1.0.0-SNAPSHOTがビルドされたら、結果のJARを「メイン」プロジェクトに配置します(例と同じように)。 libディレクトリ。私はそれを通常のMaven依存関係で動作させる方法を見つけていません。

次に、「メイン」プロジェクトでコンパイラプラグインを設定します。

<plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <release>11</release>
        <compilerArgs>
            <arg>--patch-module=jdk.unsupported=${project.basedir}/lib/Sun-misc-override-1.0.0-SNAPSHOT.jar</arg>
        </compilerArgs>
    </configuration>
</plugin>

(おそらく MCOMPILER-311 が原因で、使用しようとしたときにNPEを取得していました

<compilerArgs>
    <arg>--patch-module</arg>
    <arg>jdk.unsupported=${project.basedir}/lib/Sun-misc-override-1.0.0-SNAPSHOT.jar</arg>
</compilerArgs>

バグはmaven-compiler-plugin 3.8.0で修正されることになっていて、Sun-misc-overrideのPOMで正常に機能したとしても)

現在、私の「メイン」プロジェクトはj11と呼ばれ、1つのクラスがあります。

package com.example;

import Sun.misc.BASE64Encoder;

public class BASE64EncoderTest {
    public static void main(String[] args) {
        System.out.println("Testing - " + new BASE64Encoder().encode(new byte[0]));
    }
}

実行するには、--patch-moduleを再度指定する必要があります。

> Java --patch-module=jdk.unsupported=lib\Sun-misc-override-1.0.0-SNAPSHOT.jar -cp target\j11-1.0.0-SNAPSHOT.jar com.example.BASE64EncoderTest
Testing - Fake it until you make it!
6
Adam Michalik

過去のバージョンでは、Sunは、現在試みている方法でランタイムを改ざんする方法がないことを確認するために多大な努力を払いました(これほど簡単だったのであれば、誰もがランタイムの独自のプライベートバリアントを作成できたでしょう-そして確かにあなたはそれが良いことではなかっただろうと理解するでしょう)。詳細はわかりませんが、「パッケージ名がthisまたはthatなどの場合、ロードはrt.jarからのみ行われます」-クラスローダーのハードコードにハードコードされています。それらの強制措置(または同様の)がまだ有効である可能性が非常に高いようです。

あなたの選択肢が何であるかをよく理解していると思うので、それは問題ではなかったので、私の答えの残りを捨てました。

3
Erwin Smout