修补java.base结果导致java.lang.LinkageError

时间:2019-02-11 17:08:26

标签: java classpath java-11 java-module jigsaw

我正在尝试在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条指令,因此我怀疑这是问题所在。

1 个答案:

答案 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选项对它们进行编译。