我们如何使用 –patch-module 来覆盖来自 OpenJDK 11 的 java.base/java.lang.Integer?

huangapple go评论72阅读模式
英文:

How can we overwrite java.base/java.lang.Integer from OpenJDK 11 using --patch-module?

问题

在JDK-8中,我们可以编译已更改的java.lang类并重建rt.jar。然后,我们可以通过在引导类路径中添加-Xbootclasspath:<yourpathto>/rt.jar来覆盖java.lang类文件。通过这样做,例如,我们可以使java.lang.Integer在测试目的下变为非final。

在JDK-11中,情况不同。修补是通过--patch-modules进行的,但我无法使其工作。我已经执行了以下操作:

  1. 删除了java.base模块的final修饰符并从openjdk-11源代码重新编译了java.base模块。
  2. 添加了--patch-module java.base=<path-to-my-compiled-java.base-directory>
  3. 仍然出现error: cannot inherit from final Integer错误。可能我们不能再覆盖JDK源文件的类声明了?这会很奇怪。
  4. 我还尝试将这些类文件添加到一个jar中,并尝试将所有可能的根目录传递给--patch-module参数。
  5. 我尝试从编译的java.base目录中删除模块package-info.class,并尝试使用--add-opens显式添加java.base.java.lang.Integer

文档对于这种特定的用法并不是很清楚。

来自Maven的完整javac命令(我尝试过javac和maven-compiler-plugin):

javac -d ./target/classes -classpath <classpathfiles> -sourcepath <sourcefiles> -s ./target/generated-sources/annotations -g -nowarn -target 11 -source 11 -encoding UTF-8 --patch-module=java.base=../runtimejar/mods/src/java.base -Xplugin:Manifold

(为了可读性,缩短了路径名等)

我在这里漏掉了什么?为什么我不能像这样修改java.base/java.lang.Integer

英文:

In the JDK-8, we could compile our changed java.lang classes and reconstruct the rt.jar. Then we could overwrite java.lang classfiles by augmenting the bootclasspath with -Xbootclasspath:<yourpathto>/rt.jar. Doing this, we could for example make java.lang.Integer be non-final for testing purposes.

In JDK-11, this is different. Patching is done via --patch-modules and I can't get it to work. I have done the following:

  1. Remove the final modifier and recompiled the java.base module from the openjdk-11 source
  2. Added the --patch-module java.base=<path-to-my-compiled-java.base-directory>
  3. It still fails on error: cannot inherit from final Integer. Possibly we can't overwrite the class declarations of JDK source files anymore? That would be strange.
  4. I've also tried adding these classfiles to a jar and tried to pass all possible root directories to the --patch-module argument
  5. I've tried removing the module package-info.class from the compiled java.base directory and tried explicitly adding java.base.java.lang.Integer with --add-opens

The docs aren't really clear on this particular usage.

The entire javac command from maven (I have tried both javac and the maven-compiler-plugin):

javac -d ./target/classes -classpath <classpathfiles> -sourcepath <sourcefiles> -s ./target/generated-sources/annotations -g -nowarn -target 11 -source 11 -encoding UTF-8 --patch-module=java.base=../runtimejar/mods/src/java.base -Xplugin:Manifold

(Shortened path names etc. for readability)

What am I missing here? Why can't I modify java.base/java.lang.Integer like this?

答案1

得分: 3

以下是翻译好的内容:

来自Project Jigsaw的示例模型适用于您的用例。请注意在javac和java中使用--patch-module。

--patch-module

从Doug Lea的CVS中签出java.util.concurrent类的开发人员将用于编译源文件并使用-Xbootclasspath/p部署这些类。

-Xbootclasspath/p已被移除,其模块替代品是选项--patch-module,用于覆盖模块中的类。它还可以用于增加模块的内容。--patch-module选项也受javac支持,以便将代码编译为模块的一部分。

以下是一个示例,编译了java.util.concurrent.ConcurrentHashMap的新版本,并在运行时使用它:

javac --patch-module java.base=src -d mypatches/java.base \
    src/java.base/java/util/concurrent/ConcurrentHashMap.java
    
java --patch-module java.base=mypatches/java.base ...

确保您的源路径与--patch-module目录对齐,即src/java.base/java/lang/Integar.java文件是否存在,并且是否在您的源路径中?

更新

以下是一个演示如何对java.lang.Integer进行影响的示例项目:链接

编译:

javac --patch-module java.base=src -d mypatches/java.base src/java.base/java/lang/Integer.java
javac --patch-module java.base=mypatches/java.base -d target src/main/java/com/example/MyInteger.java src/main/java/com/example/RunMe.java

运行:

java --patch-module java.base=mypatches/java.base -classpath target com.example.RunMe
英文:

The example from Project Jigsaw models your use-case. Note the use of --patch-module for both javac and java.

>### --patch-module
>
>Developers that checkout java.util.concurrent classes from Doug Lea's CVS will be used to compiling the source files and
> deploying those classes with -Xbootclasspath/p.
>
> -Xbootclasspath/p has been removed, its module replacement is the option --patch-module to override classes in a module. It can also be
> used to augment the contents of module. The --patch-module option is
> also supported by javac to compile code "as if" part of the module.
>
> Here's an example that compiles a new version of
> java.util.concurrent.ConcurrentHashMap and uses it at run-time:
>
> javac --patch-module java.base=src -d mypatches/java.base \
> src/java.base/java/util/concurrent/ConcurrentHashMap.java
>
> java --patch-module java.base=mypatches/java.base ...
>

Check that your sourcepath aligns with your --patch-module directory i.e., is there a file src/java.base/java/lang/Integar.java and is it in your sourcepath?

Update

Here is a sample project that demonstrates how to shadow java.lang.Integer: https://dl.dropbox.com/s/6swet2k89vukxbm/patch.zip

Compile:

javac --patch-module java.base=src -d mypatches/java.base src/java.base/java/lang/Integer.java
javac --patch-module java.base=mypatches/java.base -d target src/main/java/com/example/MyInteger.java src/main/java/com/example/RunMe.java

Run:

java --patch-module java.base=mypatches/java.base -classpath target com.example.RunMe

huangapple
  • 本文由 发表于 2020年8月15日 05:09:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63420048.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定