Исправление результатов java.base в java.lang.LinkageError - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь сделать то же самое в Java 11, что можно сделать с помощью -Xbootclasspath/p:path в pre java 9.

В качестве простого примера я изменил один из valueOf методов java.lang.Integerи скомпилировал проект с:

javac --module-source-path=src/java.base --patch-module java.base=src/java.base -d mods $(find src -name '*.java')

Затем я запустил простой пример, используя:

java --patch-module java.base=<pathToMyModifiedJavaBaseClasses> -p lib -m my.moduleA/my.moduleA.Main

Это сработаловидя отображаемые изменения (простую распечатку я сделал с valueOf).

Когда я пытаюсь сделать то же самое с java.lang.ClassLoader, я получаю следующую ошибку при выполнении программы (компиляция работает):

Error occurred during initialization of boot layer java.lang.LinkageError: loader 'bootstrap' attempted duplicate class definition for java.lang.invoke.SimpleMethodHandle.

Мне даже не нужно вносить изменения в java.lang.ClassLoader.Само существование этого класса в моей папке с патчами, кажется, провоцирует эту ошибку.(Я хотел добавить только поле внизу класса)

ПРИМЕЧАНИЕ. Я только что подумал, что это работает, когда класс ClassLoader скомпилирован с Eclipse.Одно из немногих отличий, которое я знаю, заключается в том, что компилятор Eclipse, похоже, пока не следует JEP 280 .Но в байт-коде есть также инструкции invokedynamic, полученные из javac, поэтому я сомневаюсь, что это проблема.

1 Ответ

0 голосов
/ 12 февраля 2019

Вы уже указали в правильном направлении.Он работает, когда вы компилируете класс с вашей текущей версией Eclipse, потому что этот компилятор пока не следует JEP 280 , поэтому он не использует invokedynamic для конкатенации строк.

Thisне означает, что использование invokedynamic в ClassLoader в целом проблематично.Это проблематично только в некоторых критических путях кода, выполняемых во время начальной загрузки пакета java.lang.invoke, и, очевидно, этот класс использует конкатенацию строк в этом пути кода.

В случае javac вы можете принудительно вызватьиспользование старого кода конкатенации строк через опцию
-XDstringConcat=inline.Глядя на байт-код ClassLoader.class, поставляемый с JDK, кажется, что этот класс был скомпилирован с этой опцией.На самом деле, глядя на некоторые примеры, кажется, что весь модуль java.base был скомпилирован с этой опцией, в отличие, например, от java.desktop, классы которого используют invokedynamic для конкатенации строк.

Так чтовывод заключается в том, что для исправления классов в модуле java.base (в OpenJDK и его производных) скомпилируйте их, используя параметр -XDstringConcat=inline при использовании javac.

...