I am trying to do the same thing in Java 11 that could be done with -Xbootclasspath/p:path
in pre java 9.
As a simple example I modified one of the valueOf
methods of java.lang.Integer
and compiled the project with:
javac --module-source-path=src/java.base --patch-module java.base=src/java.base -d mods $(find src -name '*.java')
I then ran a simple sample using:
java --patch-module java.base=<pathToMyModifiedJavaBaseClasses> -p lib -m my.moduleA/my.moduleA.Main
That worked an I'm seeing the modifications displayed (a simple print out I did from valueOf
).
When I try, however, to do the same thing with java.lang.ClassLoader
I get the following error when executing the program (compile works):
Error occurred during initialization of boot layer java.lang.LinkageError: loader 'bootstrap' attempted duplicate class definition for java.lang.invoke.SimpleMethodHandle.
I do not even need to make changes in java.lang.ClassLoader
. The sheer existence of that class in my patch folder seems to be provocing this error. (I only wanted to add a field though at the bottom of the class)
NOTE: I just figured that it works when the ClassLoader
class is compiled with Eclipse. One of the few differences I know is that the Eclipse compiler does not seem to follow JEP 280 yet. But there are invokedynamic
instructions in the bytecode resulting from javac
as well, so I doubt that this is the problem.
You did already point into the right direction. It works when you compile the class with your current version of Eclipse, because that compiler does not follow JEP 280 yet, so it doesn’t use invokedynamic
for string concatenation.
This does not imply that using invokedynamic
in ClassLoader
is problematic in general. It is only problematic in certain critical code paths executed during the bootstrapping of the java.lang.invoke
package and apparently, this class does use string concatenation on this code path.
In case of javac
, you can force the use of the old string concatenation code via the option
-XDstringConcat=inline
. Looking into the bytecode of the ClassLoader.class
as shipped with the JDK, it seems this class has been compiled with this option. In fact, looking at some samples, it seems the entire java.base
module has been compiled with that option, in contrast to, e.g. java.desktop
, whose classes use invokedynamic
for string concatenation.
So the conclusion is, to patch classes in the java.base
module (in OpenJDK and derivatives), compile them using the -XDstringConcat=inline
option when using javac
.