Tomcat 9的通用类加载器是URLClassLoader吗?

huangapple go评论63阅读模式
英文:

Is Tomcat 9 common classloader a URLClassLoader?

问题

I have a custom library used by all of my applications that usually resides in the common library set of catalina.properties. It assumes that the classloader is a URLClassLoader.

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

Under Java 8 even the basic AppClassLoader could be cast to URLClassLoader, and so could the classloader used by Tomcat 8 (which I suspect was a custom classloader made by the Tomcat designers).

在Java 8中,即使是基本的AppClassLoader也可以强制转换为URLClassLoader,Tomcat 8使用的类加载器也可以这样做(我怀疑这是Tomcat设计者制作的自定义类加载器)。

So, under Java 9-11, in Tomcat 9... can I expect the common classloader to be a URLClassLoader? If not, what is it? And would there be a way for me to design a URLClassloader that could be plugged in to make common use it?

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

Thanks. 感谢。

英文:

I have a custom library used by all of my applications that usually resides in the common library set of catalina.properties. It assumes that the classloader is a URLClassLoader.

Under Java 8 even the basic AppClassLoader could be cast to URLClassLoader, and so could the classloader used by Tomcat 8 (which I suspect was a custom classloader made by the Tomcat designers).

So, under Java 9-11, in Tomcat 9... can I expect the common classloader to be a URLClassLoader? If not, what is it? And would there be a way for me to design a URLClassloader that could be plugged in to make common use it?

Thanks.

答案1

得分: 2

以下是翻译好的部分:

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及以后的版本中,它不再是一个简单的URLClassLoader,因为有了模块系统。

  • 输出中的第四个是Java Extension/Platform 类加载器。在Java 8及之前的版本中,它是一个URLClassLoader。在Java 9及以后的版本中,它不再是一个简单的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
   

<details>
<summary>英文:</summary>

***TL;DR:** The common classloader of Tomcat 9 is a `URLClassLoader`*

To check which classloaders are used by a Tomcat application, create a small servlet to list the `ClassLoader` hierarchy.

```lang-java
@WebServlet(&quot;/testcl&quot;)
public class ClassLoaderTest extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType(&quot;text/plain&quot;);
		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(&quot;    &quot; + url);
		}
	}
}

Deploy to Tomcat and open the page of the servlet, e.g. http://localhost:8080/test/testcl

The shown page lists the classloaders and the URLs if the classloader is a URLClassLoader.

As can be seen in the output below, both the webapp classloader and the common classloader are URLClassLoader's:

  • The 1st in the output is the Tomcat WebApp classloader, listing the WEB-INF/classes folder of the test webapp. It would also have listed any jar files in the WEB-INF/lib folder, if there had been any.
    It is a URLClassLoader.

  • The 2nd in the output is the Tomcat Common classloader, listing the Tomcat lib folder and all the jar files found in that folder.
    It is a URLClassLoader.

  • The 3rd in the output is the Java App classloader, representing the CLASSPATH of the Java application.
    In Java 8 and earlier, it is a URLClassLoader. In Java 9 and later, it is not a simple URLClassLoader any more, because of the Module system.

  • The 4rd in the output is the Java Extension/Platform classloader.
    In Java 8 and earlier, it is a URLClassLoader. In Java 9 and later, it is not a simple URLClassLoader any more, because of the Module system.

  • Not shown in output, because it is represented by the null value, is the Java Bootstrap classloader.

Sample output with 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

Sample output with 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

答案2

得分: -1

Tomcat 9仍然使用URLClassLoader用于common和以后的类加载器。

确定方法

  1. 初步测试已经确认web应用程序使用了URLClassLoader。但由于Tomcat使用它自己的ClassLoader来启动web应用程序,这并不能回答Tomcat在达到web应用程序初始化阶段之前发生了什么

  2. 因此,要在web应用程序初始化阶段之前识别common类加载器使用的ClassLoader,我不得不使用一些奇怪的技巧:

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

希望这个答案对那些在Java 9及更高版本中遇到同样问题的人有所帮助,他们在谷歌搜索时可能会找到这个答案。

英文:

ANSWER:
Tomcat 9 still uses URLClassLoader for the common and later classloaders.

METHOD OF DETERMINATION:

  1. The initial tests with a webapp had already confirmed that webapps used a URLClassLoader. But since Tomcat launches webapps with their own ClassLoader, that does not answer what happens... before Tomcat reaches the webapp initialization stage.

  2. So, to identify the classloader used by the common classloader before the webapp initialization stage I had to use some weird tricks:

  • Switched Tomcat logging to log4j
  • Created a custom appender
  • Placed the custom appender in the common library
  • Configured log4j.xml to use the custom appender
  • Added code to the appender to display the name and class of the classloader used by the appender.
  • Since log4j logging gets activated by Tomcat before initializing any web applications, as demonstrated by the log4j entries... it answers the question.

I hope this answer is useful to those that stumble onto the same problem with Java 9 and later, and arrive to it when they google.

huangapple
  • 本文由 发表于 2020年8月11日 07:45:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/63349548.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定