4

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?

LatencyFighter
  • 351
  • 2
  • 11
  • 1
    Possible duplicate of [How should I load Jars dynamically at runtime?](https://stackoverflow.com/questions/60764/how-should-i-load-jars-dynamically-at-runtime) – tsolakp Feb 08 '18 at 16:59
  • Regarding bootstrap class loader: https://stackoverflow.com/questions/22556929/getting-a-list-of-all-the-bootstrap-classes-on-the-jvm. I would advise to use custom `ClassLoader`. – tsolakp Feb 08 '18 at 17:00
  • Bootstrap classloader is very different. Not a duplicate. – LatencyFighter Feb 08 '18 at 17:09
  • Did you see my other comment. It can be impossible to access bootstrap class loader. – tsolakp Feb 08 '18 at 17:10

2 Answers2

8

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.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • Thanks, maybe I'm missing something basic about ClassLoader's black magic. What I'm trying to do is to load a class from a jar into the bootstrap classpath, so subsequent classes loaded normally by the bootstrap can know about this external class without throwing a ClassNotFoundException. – LatencyFighter Feb 08 '18 at 17:31
  • 1
    The phrase “load a class … into the bootstrap classpath” doesn’t make much sense. You can add jar files to the bootstrap class path, but not single classes. If you want to enforce the creation of a runtime class as-if being loaded through the bootstrap class loader, there is no standard API for that, only hacks. – Holger Feb 08 '18 at 17:36
  • typo => "into the bootstrap **classloader**" => I'm interested in such a hack :) – LatencyFighter Feb 08 '18 at 17:42
  • @LatencyFighter Do you want to "patch" one of the RT classes? Or the like? Are the [extension-loader or the application loader](https://blogs.oracle.com/sundararajan/understanding-java-class-loading) not an option? I don't really see the need to mess around with the bootstrap classes – Roman Vottner Feb 08 '18 at 17:49
  • @RomanVottner Thanks for the link but I really need to do that programmatically, not through the command-line. Please check this question: https://stackoverflow.com/questions/48691773/is-it-possible-to-force-someone-elses-java-classloader-to-load-an-external-byte – LatencyFighter Feb 08 '18 at 17:51
  • @LatencyFighter do you have any extensions that require that class and you want to ensure that the class is available? Or are just some classes loaded on application startup requiring this class? – Roman Vottner Feb 08 '18 at 17:54
  • Some classes loaded by the bootstrap classloader require this external class. So the bootstrap classloader must know about this external class. This is happening on the bootstrap classloader, not on the regular application classloader. That's why simply adding my class to the regular classpath won't work. I also can't add to the bootclasspath command-line, need to do this programatically. – LatencyFighter Feb 08 '18 at 17:56
  • 2
    @LatencyFighter the other question regarding the system class loader was easy to answer, as there is an existing `ClassLoader` instance then, rather than the bootstrap class loader represented by `null`. Admittedly, I was a bit surprised that there is no such option for Java Agents to simply define a class, but well, I expanded my answer and listed all options that I currently know of. – Holger Feb 08 '18 at 18:23
  • I'm trying to load a class through the bootstrap class loader, using `Class.forName("com.mypackage.MyClass", true, null); new MyClass();`, and getting `ClassNotFoundException` on the first line. How do I make a class discoverable by the bootstrap class loader? – spongebob Aug 07 '20 at 21:27
  • 1
    @FrancescoMenzani that’s something you should not do. You are not supposed to add your ordinary application classes to the bootstrap loader. Besides that, there is no point in having a reflective class loading using `Class.forName(…)` followed by a non-reflective use like `new MyClass()`. The latter will already load the class. – Holger Aug 10 '20 at 07:57
  • I would do that to enable annotations like `@Stable` and `@ForceInline` in application code. Is there no way to do it? `new MyClass()` alone would use the application class loader, that is why I'm loading the class reflectively before. – spongebob Aug 10 '20 at 12:07
  • 2
    @FrancescoMenzani `new MyClass()` will ask the application class loader which will in turn ask the parent loader first, so if the class is on the bootstrap path, it will be loaded by the bootstrap loader. Loading it reflectively first does not influence that logic. The options to manipulate the bootstrap class loading path [are documented](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html#BABHDABI)… – Holger Aug 10 '20 at 12:42
  • Class integer = (Class) Class.forName("java.lang.Integer", true, null); System.out.println(integer.getClassLoader() + " | " + integer.hashCode()); --> null | 2018699554 Class b = (Class) Class.forName("com.test.aggregation.B", true, null); System.out.println(b.getClassLoader() + " | " + b.hashCode()); --> Exception in thread "main" java.lang.ClassNotFoundException: com/test/aggregation/B – hagrawal7777 May 08 '21 at 12:47
  • Above code sample tells me that using bootstrap classloader you cannot load a user-defined class. Is it correct? – hagrawal7777 May 08 '21 at 12:48
  • 1
    @hagrawal if your class is only provided through the normal class path (or module path) , it is not visible to the bootstrap loader. So yes, under these normal circumstances, you can’t load your class using the bootstrap loader. And normally, there is no need to. – Holger May 10 '21 at 08:21
  • Ok, thank you @Holger. I wanted to confirm my understanding. Could you please update your answer to include this point? – hagrawal7777 May 11 '21 at 13:27
0

A somewhat roundabout way to load classes via the bootstrap class loader is to define your own class loader like so:

    ClassLoader bootClassLoader = new ClassLoader(null){};

This class loader has no parent and thus the only place it will load classes from is the inherent bootstrap class loader.

michid
  • 10,536
  • 3
  • 32
  • 59