【问题标题】:Is Tomcat 9 common classloader a URLClassLoader?Tomcat 9 通用类加载器是 URLClassLoader 吗?
【发布时间】:2020-08-10 23:45:58
【问题描述】:

我的所有应用程序都使用了一个自定义库,该库通常位于 catalina.properties 的公共库集中。它假定类加载器是一个 URLClassLoader。

在 Java 8 下,即使是基本的 AppClassLoader 也可以转换为 URLClassLoader,Tomcat 8 使用的类加载器也可以(我怀疑它是 Tomcat 设计人员制作的自定义类加载器)。

那么,在 Java 9-11 下,在 Tomcat 9 中... 我可以期望 common 类加载器是 URLClassLoader 吗? 如果不是,它是什么?有没有办法让我设计一个可以插入的 URLClassloader 以使 common 使用它?

谢谢。

【问题讨论】:

  • Tomcat 是开源的,你可以修改代码并让它做你想做的任何事情(或者更确切地说,任何你能想到的代码)。 --- 至于常见的loader是不是一个URLClassLoader,你自己去看看吧?投射或使用instanceof。问题被否决,因为它“没有显示任何研究工作”(引用的否决按钮工具提示)
  • “编码天数”?只需要 分钟 创建一个空的 web 应用程序,它只是测试公共类加载器是否是 URLClassLoader。这就是所谓的研究,即搜索信息,在这种情况下是通过实验。在发现关键部分不起作用之前,我绝不会建议迁移整个 Web 应用程序。那将是可笑的!
  • 仅供参考:如果您只是简单地进行了自己的研究,那么您已经对您的问题有了明确的答案。从你开始写这个问题到现在已经超过 2.5 个小时,你仍然没有答案。 --- How much research effort is expected of Stack Overflow users?

标签: java tomcat classloader


【解决方案1】:

TL;DR: Tomcat 9 的常见类加载器是 URLClassLoader

要检查 Tomcat 应用程序使用了哪些类加载器,请创建一个小 servlet 以列出 ClassLoader 层次结构。

@WebServlet("/testcl")
public class ClassLoaderTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/plain");
        PrintWriter out = resp.getWriter();
        for (ClassLoader cl = Thread.currentThread().getContextClassLoader(); cl != null; cl = cl.getParent()) {
            out.println(cl.getClass().getName());
            if (cl instanceof URLClassLoader)
                for (URL url : ((URLClassLoader) cl).getURLs())
                    out.println("    " + url);
        }
    }
}

部署到 Tomcat 并打开 servlet 的页面,例如http://localhost:8080/test/testcl

如果类加载器是URLClassLoader,则显示的页面会列出类加载器和 URL。

从下面的输出中可以看出,webapp 类加载器common 类加载器 都是 URLClassLoader 的:

  • 输出中的第一个是 Tomcat WebApp 类加载器,列出了 test webapp 的 WEB-INF/classes 文件夹。如果有的话,它还会列出WEB-INF/lib 文件夹中的所有 jar 文件。
    这是一个URLClassLoader

  • 输出中的第二个是 Tomcat Common 类加载器,列出了 Tomcat lib 文件夹以及在该文件夹中找到的所有 jar 文件。
    这是一个URLClassLoader

  • 输出中的第三个是 Java App 类加载器,代表 Java 应用程序的 CLASSPATH。
    在 Java 8 及更早版本中,它是 URLClassLoader。在 Java 9 及更高版本中,由于 Module 系统,它不再是简单的URLClassLoader

  • 输出中的第四个是 Java Extension/Platform 类加载器。
    在 Java 8 和更早版本中,它是 URLClassLoader。在 Java 9 及更高版本中,由于 Module 系统,它不再是简单的URLClassLoader

  • 未显示在输出中,因为它由 null 值表示,是 Java Bootstrap 类加载器。

Java 8 的示例输出

org.apache.catalina.loader.ParallelWebappClassLoader
    file:/C:/prog/tomcat-9.0.27/webapps/test/WEB-INF/classes/
java.net.URLClassLoader
    file:/C:/prog/tomcat-9.0.27/lib/
    file:/C:/prog/tomcat-9.0.27/lib/annotations-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina-ant.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina-ha.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina-storeconfig.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina-tribes.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina.jar
    file:/C:/prog/tomcat-9.0.27/lib/ecj-4.13.jar
    file:/C:/prog/tomcat-9.0.27/lib/el-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/jasper-el.jar
    file:/C:/prog/tomcat-9.0.27/lib/jasper.jar
    file:/C:/prog/tomcat-9.0.27/lib/jaspic-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/jsp-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/servlet-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-coyote.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-dbcp.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-cs.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-de.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-es.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-fr.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-ja.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-ko.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-pt-BR.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-ru.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-zh-CN.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-jdbc.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-jni.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-util-scan.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-util.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-websocket.jar
    file:/C:/prog/tomcat-9.0.27/lib/websocket-api.jar
sun.misc.Launcher$AppClassLoader
    file:/C:/prog/tomcat-9.0.27/bin/bootstrap.jar
    file:/C:/prog/tomcat-9.0.27/bin/tomcat-juli.jar
sun.misc.Launcher$ExtClassLoader
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/access-bridge-64.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/cldrdata.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/dnsns.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/jaccess.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/jfxrt.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/localedata.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/nashorn.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/sunec.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/sunjce_provider.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/sunmscapi.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/sunpkcs11.jar
    file:/C:/prog/Java64/jdk1.8.0_181/jre/lib/ext/zipfs.jar

Java 14 的示例输出

org.apache.catalina.loader.ParallelWebappClassLoader
    file:/C:/prog/tomcat-9.0.27/webapps/test/WEB-INF/classes/
java.net.URLClassLoader
    file:/C:/prog/tomcat-9.0.27/lib/
    file:/C:/prog/tomcat-9.0.27/lib/annotations-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina-ant.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina-ha.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina-storeconfig.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina-tribes.jar
    file:/C:/prog/tomcat-9.0.27/lib/catalina.jar
    file:/C:/prog/tomcat-9.0.27/lib/ecj-4.13.jar
    file:/C:/prog/tomcat-9.0.27/lib/el-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/jasper-el.jar
    file:/C:/prog/tomcat-9.0.27/lib/jasper.jar
    file:/C:/prog/tomcat-9.0.27/lib/jaspic-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/jsp-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/servlet-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-api.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-coyote.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-dbcp.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-cs.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-de.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-es.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-fr.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-ja.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-ko.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-pt-BR.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-ru.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-i18n-zh-CN.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-jdbc.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-jni.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-util-scan.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-util.jar
    file:/C:/prog/tomcat-9.0.27/lib/tomcat-websocket.jar
    file:/C:/prog/tomcat-9.0.27/lib/websocket-api.jar
jdk.internal.loader.ClassLoaders$AppClassLoader
jdk.internal.loader.ClassLoaders$PlatformClassLoader

【讨论】:

  • 问题不是关于 webapp 类加载器,而是关于 common 类加载器。它们不是同一个类加载器。我在之前的回复中反复说过,我不再看到了。通过专注于 webapp 类加载器,您会误导和混淆任何非专家并阅读此线程的人。 common 和 webapp 类加载器是两个完全独立的类加载器,它们甚至与它们的父类加载器有不同的关系。
  • @user321974 请阅读我写的内容,我不只是在写无用的文本。这个答案也完全涵盖了 common 类加载器。类加载器被组织成一个层次结构,对于 Tomcat,有 4 个类加载器适用于一个 webapp:1)WebApp 类加载器(由 Tomcat 管理),2)通用类加载器(由Tomcat),3)引导类加载器,又名“应用程序”(由 JVM 管理),4)Ext/Platform 类加载器(由 JVM 管理)。 common classloader 是输出中列出的第二个类加载器,包含 Tomcat lib 文件夹及其所有 jar 文件。
  • 我现在明白了。谢谢。
【解决方案2】:

回答:
Tomcat 9 仍将 URLClassLoader 用于 common 和更高版本的类加载器。

确定方法:

  1. 对 webapp 的初始测试已经确认 webapps 使用了 URLClassLoader。但是由于 Tomcat 使用自己的 ClassLoader 启动 webapps,这并不能回答会发生什么......在 Tomcat 到达 webapp 初始化阶段之前

  2. 因此,为了在 webapp 初始化阶段之前识别 common 类加载器使用的类加载器,我不得不使用一些奇怪的技巧:

  • 将 Tomcat 日志记录切换到 log4j
  • 创建了自定义附加程序
  • 将自定义附加程序放在公共库中
  • 将 log4j.xml 配置为使用自定义附加程序
  • 向 appender 添加了代码以显示 appender 使用的类加载器的名称和类。
  • 由于 log4j 日志记录在初始化任何 Web 应用程序之前由 Tomcat 激活,如 log4j 条目所示......它回答了这个问题。

我希望这个答案对那些在 Java 9 及更高版本中偶然发现相同问题并在谷歌上找到它的人有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多