30thh
30thh

Reputation: 11406

Which classloader loaded a class of the provided instance

In JEE environment it is useful to know, where a particular class is loaded from.

For example I have an instance of org.slf4j.Logger provided by a some black box library. Is it possible to find the responsible classloader? If the class of the instance comes from JDK, Application Server, EAR or Web Application classloader?

Upvotes: 3

Views: 281

Answers (1)

30thh
30thh

Reputation: 11406

It turns out to be quite simple. The name of the classloader is returned by:

object.getClass().getClassLoader().getName()

It returns something like "app" or "platform". Be careful - classloader is null, if the class belongs to the bootstrap classloader, like the JUL logger java.util.logging.Logger does.

WebLogic has a long chain of classloaders without names. WebLogic's classloaders contain a useful field annotation. One can read it to find the JEE application, the classloader belongs to:

public Object getAnnotation(ClassLoader classloader) {
    try {
        Method amethod = classloader.getClass().getMethod("getAnnotation");
        return amethod.invoke(classloader);
    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
        return "";
    }
}

If you want to print an overview of all available classloader without digging for annotations, the hashcode of the classloader instance can be used. Here is a small JSP page. Put it into the webapp directory of your web project to get a quick overview.

<%
response.setContentType("text/plain");

List<Class<?>> clazzes = List.of(Logger.class, object.getClass());

out.println("CLASSLOADERS:\n");
ClassLoader classloader = new Object() {}.getClass().getClassLoader();
while (classloader != null) {
    out.println(
            String.format("%-18s", classloader.getName()) + " " +
            String.format("%-10s", Integer.toHexString(classloader.hashCode()))  + " " + 
            classloader.getClass().getName() + " / " + getAnnotation(classloader));

    classloader = classloader.getParent();
}

out.println("\nCLASSES:\n");
for (Class<?> clazz : clazzes) {
    ClassLoader cloader = clazz.getClassLoader();
    URL location = Optional.of(clazz.getProtectionDomain()).map(x->x.getCodeSource()).map(x->x.getLocation()).orElse(null);
    out.println(
            clazz + " \n    " + 
            (cloader != null ? Integer.toHexString(cloader.hashCode()) : "<bootstrap>") + "\t" + 
            location);
}

%>

Upvotes: 2

Related Questions