Search code examples
javaclassloader

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?


Solution

  • 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);
    }
    
    %>