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

问题描述 投票:0回答:2

我正在尝试在 Java 11 中做同样的事情,这可以在 Java 9 之前的

-Xbootclasspath/p:path
中完成。

作为一个简单的例子,我修改了

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
指令,所以我怀疑这是问题所在。

java classpath java-11 java-module java-platform-module-system
2个回答
5
投票

您确实已经指出了正确的方向。当您使用当前版本的 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
选项编译它们。


0
投票

要修补 java.base 模块中的类(在 OpenJDK 和衍生产品中),在使用 javac 时使用

-XDstringConcat=inline
选项编译它们。

除此处外,其他任何地方都没有记录,但是如果没有此标志,您将收到此错误

java.lang.LinkageError: loader 'bootstrap' attempted duplicate class definition for java.lang.invoke.SimpleMethodHandle.

为了清楚起见,我只是从上面的 +4 帖子中提取这个。

© www.soinside.com 2019 - 2024. All rights reserved.