Java类装入器:为什么先搜索父类装入器?

2022-09-02 21:20:15

Java 中类装入器的正确行为是:

  1. 如果已加载,则返回类
  2. 调用父 loadClass()
  3. 尝试加载类本身。

因此,应始终首先加载系统类路径中定义的类。Tomcat 为每个 war 定义了类装入器,它将系统类装入器作为父级,因此,如果您尝试装入一个类,它将首先在系统类路径中查找,然后在 war 文件中定义的类路径中查找。

根据我的理解,这有两个原因:

  1. 避免使用不同版本的类的问题。想象一下,我在一场战争中重新定义了java.lang.Object,这将是一场噩梦。
  2. 为了避免依赖子类装入器:系统类装入器不能依赖于子类装入器:例如,很难重新部署战争。

所以,问题是:

除了上述问题之外,实现不首先进行父搜索的类装入器是否还有其他陷阱?


答案 1

Tomcat 不会首先查找父类装入器。实际上它的作用恰恰相反:它首先在web应用程序中查找,然后才进入父类加载器(对于Tomcat 6/7是“lib”,对于Tomcat 5.5是“共享”)。这个规则的例外是系统类(我认为所有包含java.*和javax.*的类都是如此),这些类只在系统类装入器中查找。我相信他们这样做的原因是你说的#1原因。

因此,基本上可以实施父优先策略。实现父最后一次也是可以的。这两种策略都有其优点和优点。

我再给你一个原因,为什么要实现父级优先:你减少了烫发内存中加载的类的数量。假设您有多个 Web 应用程序使用相同的库。使用父级优先,库加载一次。使用父项-last,它将被加载多次。
但是,对于父级优先,所有 Web 应用都需要使用相同版本的库,而对于父级优先,它们可能使用不同的版本。


答案 2

没有。事实上,这就像实例化一个并为父级提供它一样简单:URLClassLoadernull

myClassLoader = new URLClassLoader(myUrlArray, null);

http://download.oracle.com/javase/6/docs/api/java/net/URLClassLoader.html


推荐