Mark Roberts
Mark Roberts

Reputation: 101

In Java, is it possible to know whether a class has already been loaded when using the bootstrap loader?

This is a variation of In Java, is it possible to know whether a class has already been loaded?. Our app does byte code instrumentation and makes use of the -Xbootclasspath/a: option to be able to instrument the Java runtime. I would like to know if a class has been loaded via the bootstrap loader - without attempting to load it.

The code listed in the referenced query will not work if class was loaded by bootstrap loader - as I don't believe there is any way to get an instance of the bootstrap loader to use in the invoke.

Any thoughts? I suspect it can't be done. It's not critical to our application but I am curious.

Upvotes: 2

Views: 385

Answers (2)

Holger
Holger

Reputation: 298113

When you want to perform runtime byte code instrumentation, you should implement a Java Agent using the Instrumentation API.

The Java Agent will get an Instrumentation instance in its premain or agentmain method when its parameter types have been declared as (String agentArgs, Instrumentation inst).

This API allows appending jar files to the bootstrap class path at runtime, so you don’t need to rely on the -Xbootclasspath/a option being specified on the command line.

Further, it has the methods getAllLoadedClasses() and getInitiatedClasses(ClassLoader) to query already loaded classes. So you can use getInitiatedClasses(null) to get all classes currently loaded by the bootstrap loader. You have to iterate them and compare the names yourself to find out whether a particular class in contained is the array.

Upvotes: 3

Marcio Lucca
Marcio Lucca

Reputation: 380

Ok, crazy idea.

You can use the same technique in the thread you described, trying a different method. Class ClassLoader has the following method:

private Class<?> findBootstrapClassOrNull(String name)

This method calls a native method:

private native Class<?> findBootstrapClass(String name)

Which you could try to make accessible too.

EDIT: I've tried the following code, running from application class loader, though:

public class MyClassLoader extends ClassLoader {
    public static void main(String[] args)
            throws NoSuchMethodException,
            InvocationTargetException,
            IllegalAccessException {
        Method method = ClassLoader.class.getDeclaredMethod(
                "findBootstrapClass", String.class);
        method.setAccessible(true);
        MyClassLoader cl = new MyClassLoader();
        System.out.println(method.invoke(cl, "java.lang.String"));
        System.out.println(method.invoke(cl, "sun.java2d.loops.GraphicsPrimitiveMgr$2"));
    }
}

(By the way, this code does not have to extend ClassLoader, I just left that from a previous test where I was invoking a protected method from ClassLoader.)

Whatever classes I provide, at the point my main method is running, it appears pretty much everything is loaded, not sure. From the source code for the "findBootstrapClass" method, I see this:

    /**
     * Returns a class loaded by the bootstrap class loader;
     * or return null if not found.
     */
    private Class<?> findBootstrapClassOrNull(String name)

So, unless you get different result running at the time the code is being instrumented, I'm thinking perhaps this is not doable.

NOTE: again, the source code that I looked at is for OpenJDK 1.8

Good luck.

Upvotes: 0

Related Questions