The bootstrap class loader is represented as null
, e.g. when calling Class.getClassLoader()
. This can be fed directly to Class.forName(String,boolean,ClassLoader)
:
If the parameter loader
is null, the class is loaded through the bootstrap class loader.
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 using Class.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 a Lookup
object with the appropriate access right to a bootstrap loaded class, e.g. java.lang.Object
. There are already existing Q&A about creating such a Lookup
object 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.