哪个类加载器加载了所提供实例的类

2022-04-12 00:00:00 java classloader

在JEE环境中,了解特定类的加载位置非常有用。

例如,我有一个由某个黑匣子库提供的org.slf4j.Logger实例。有可能找到负责的类加载器吗?如果实例的类来自JDK、应用服务器、EAR或Web应用程序类加载器?


解决方案

原来很简单。类加载器的名称由:

返回
object.getClass().getClassLoader().getName()
它返回类似于&q;app&q;或&q;Platform&q;之类的内容。请注意--如果类属于引导类加载器,则类加载器是null,就像JUL记录器java.util.logging.Logger那样。

WebLogic有一长串没有名称的类加载器。WebLogic的类加载器包含一个有用的字段annotation。人们可以阅读它来找到JEE应用程序,类加载器属于:

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

如果您希望打印所有可用类加载器的概述而不挖掘注释,则可以使用类加载器实例的哈希代码。这是一个小的JSp页面。将其放到您的Web项目的webapp目录中以快速查看。

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

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

out.println("CLASSLOADERS:
");
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("
CLASSES:
");
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 + " 
    " + 
            (cloader != null ? Integer.toHexString(cloader.hashCode()) : "<bootstrap>") + "	" + 
            location);
}

%>

相关文章