I know there is a "bootstrap classloader" loading all the classes from the jre/lib (rt.jar, etc). Is it possible to get my hands on this "bootstrap classloader" in order to load an additional class from another non-java package?
I'm talking about the bootstrap classpath, which is very different than the regular classpath described on this answer: How should I load Jars dynamically at runtime?
The bootstrap class loader is represented as
null, e.g. when callingClass.getClassLoader(). This can be fed directly toClass.forName(String,boolean,ClassLoader):So, you can try to load a class explicitly through the bootstrap loader using
Class.forName(className,true,null)or resolve a class relative to another class’ context usingClass.forName(className,true,context.getClassLoader())without having to special-case the bootstrap loader.If you want to define a runtime class as-if being loaded by the bootstrap loader, there is no standard solution. There is the method
sun.misc.Unsafe.defineClass(String, byte, int, int, ClassLoader, ProtectionDomain)that allows to define a class within a particular class loader, which is a proprietary API that is likely to disappear in the future.Starting with Java 9, there is
java.lang.invoke.MethodHandles.Lookup.defineClass(byte[]), a standard method define a class within another class’ context, but it requires non-standard ways, e.g. Reflection with access override to get aLookupobject with the appropriate access right to a bootstrap loaded class, e.g.java.lang.Object. There are already existing Q&A about creating such aLookupobject for other purposes, e.g. this one. Such Reflection hacks are not guaranteed to work in future versions though.For a Java Agent, there’s also the option to dump the class file(s) into a temporary Jar file and add it to the bootstrap class path programmatically, if it doesn’t mind that this involves I/O.
There is another catch to be aware of. When you want other bootstrap loaded classes to find your class, you have to add it before the first attempt to access that class, as the JVM’s resolver will remember the result, even if it is to fail with an error.