Почему среда выполнения Java 11 игнорирует мой jar, содержащий классы sun.misc? - PullRequest
9 голосов
/ 30 мая 2019

Я пытаюсь обновить свою кодовую базу до Java 11. К сожалению, мой код зависит от сторонней библиотеки, которая внутренне использует sun.misc.BASE64Encoder и Decoder. Поскольку пакет sun.misc был удален из JRE Java 11, он не работает. Владелец этой библиотеки еще не заменил эту зависимость, поэтому я застрял на некоторое время.

Если бы у меня был контроль над кодом, я бы использовал классы java.util.BASE64, но, как я уже сказал, они приходят как транзитивная зависимость из другой библиотеки, и я не могу это изменить.

Я думал, что буду умен и создам новую банку только с этими классами, но по какой-то причине эта банка игнорируется.

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 мешает вам играть, или мне не хватает какой-либо спецификации модуля, или это ограничитель шоу?

Вот вывод

java.lang.NoClassDefFoundError: sun/misc/BASE64Encoder
at com.propsco.util.support.PropsLoader.save(PropsLoader.java:478) ~[props-client-2.2.1.jar:na]

Ответы [ 2 ]

5 голосов
/ 01 июня 2019

Этот ответ написан с использованием

> 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 были перемещены в модуль jdk.unsupported, когда система модулей была развернута в Java 9, а затем со временем удалены (см. 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, и она отлично работала в POM sun-misc-override.)

Теперь мой «основной» проект называется j11 и имеет один класс:

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!
3 голосов
/ 31 мая 2019

В прошлых версиях Sun старалась изо всех сил, чтобы гарантировать, что не было никакого способа изменить среду выполнения, как вы пытаетесь сейчас (если бы это было так просто, каждый мог бы создать свой собственный частный вариант среды выполнения - и, конечно, вы поймете, что это не было бы хорошо). Я не знаю деталей, но они, вероятно, сводились к тому, что «если имя пакета - то или иное, или то, или другое, загрузка будет происходить только из rt.jar» - жестко запрограммировано в загрузчиках классов. Вполне вероятно, что эти принудительные меры (или аналогичные) все еще действуют.

Отказался от остальной части моего ответа, потому что я думаю, что вы очень хорошо понимаете, какие у вас есть варианты, и это был не вопрос.

...