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