Accessing module internals from bytecode rewriting agent
jeremymanson at google.com
Thu Jun 15 18:31:14 UTC 2017
Thanks. We'd been tossing that around in the list of possibilities, but
hadn't gotten far enough to think about whether it would be easier or not.
My initial thought in this general direction was to write a JVMTI agent
that takes a list of JAR files as arguments. It then does two things:
- Intercepts all loads of classes using the ClassFileLoadHook, checks to
see if there is a class with that name in the JAR file, and, if so, uses
that one instead. That way, if you try to load java.util.HashMap, it will
replace the bytes the system is trying to load from rt.jar (or whatever)
with the bytes from the provided JAR.
- Puts those JARs into the bootclasspath using AddToBootstrapClassLoaderSearch,
so that the boot class loader (or whatever) can find those packages.
It has to be JVMTI instead of java.lang.instrument, of course, because many
JDK classes will already be loaded if you are far enough along to use
The advantage of this approach is that it works with unmodified JDKs 6, 7,
8 and 9, and will probably work for 95%+ of the cases. In fact, I wrote a
prototype in a couple of hundred LOC that seems to work just fine.
Because we write our own launcher and use JEP 178 pretty pervasively, I can
even just make "-Xbootclasspath/p" mean "load this JVMTI library", if I
want, and still not modify the JDK.
The disadvantages are that a) that ClassFileLoadHook will have to go before
any other transforming agents, so that subsequent transformations aren't
lost, and that b) if the user tries to get the actual bytes of the class as
a resource from the classloader, those bytes will not correspond to the
bytes that were loaded.
Your way might be better, even if it does require local changes.
Technically, there are a few folks still using Java 7 around here, which
might make it somewhat more painful. Also, making -patch-module work in
Javas 7 and 8 might be confusing to users who have to deal with stock JDKs
(or directions that are supposed to apply to stock JDKs), but maybe that's
On Thu, Jun 15, 2017 at 1:21 AM, Alan Bateman <Alan.Bateman at oracle.com>
> On 15/06/2017 01:00, Jeremy Manson wrote:
>> The upshot is that, in the same way as we would have turned on the big
>> kill switch by default to ease the transition, we are also likely to
>> implement -Xbootclasspath/p to ease the transition.
> You might find it easier to add --patch-module to your JDK 8 build
> instead. It's easy to translate a sequence of `--patch-module
> <module>=<file>(<pathsep><file>)*` options to one
> `-Xbootclasspath/p:<file>(<pathsep><file>)*`. Going the other way is not
> easy, esp. if -Xbootclasspath/p is called with a directory or JAR file
> containing classes or resources in "new" packages or where there are
> classes that are no longer defined to the boot class loader.
More information about the core-libs-dev