简体   繁体   中英

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

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?

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 ie, 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM