我正在尝试在Java 11中做与Java 9之前的-Xbootclasspath/p:path
相同的事情。
作为一个简单的示例,我修改了valueOf
的{{1}}方法之一,并使用以下代码编译了项目:
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
类是使用Eclipse编译的。我知道的几个区别之一是Eclipse编译器似乎还没有遵循JEP 280。但是ClassLoader
产生的字节码中也有invokedynamic
条指令,因此我怀疑这是问题所在。
答案 0 :(得分:4)
您确实已经指出了正确的方向。当您使用当前版本的Eclipse编译类时,它可以工作,因为该编译器尚未遵循JEP 280,因此它不使用invokedynamic
进行字符串连接。
这并不意味着在invokedynamic
中使用ClassLoader
通常是有问题的。它仅在java.lang.invoke
程序包引导期间执行的某些关键代码路径中有问题,并且显然,此类确实在此代码路径上使用字符串连接。
对于javac
,您可以通过选项强制使用旧的字符串连接代码
-XDstringConcat=inline
。查看JDK随附的ClassLoader.class
的字节码,似乎已经使用此选项编译了该类。实际上,看一些示例,似乎整个java.base
模块已使用该选项进行了编译,与之相反,例如java.desktop
,其类使用invokedynamic
进行字符串连接。
因此得出的结论是,要修补java.base
模块中的类(在OpenJDK及其衍生版本中),请在使用-XDstringConcat=inline
时使用javac
选项对它们进行编译。