Java类加载器:为什么首先搜索父类加载器?

Mat*_*ell 16 java classloader

Java中类加载器的正确行为是:

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

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

据我了解,这有两个原因:

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

所以,问题是:

除了上述问题之外,实现不首先进行父搜索的类加载器还有其他缺陷吗?

Tar*_*log 14

Tomcat首先不查找父类加载器.实际上它恰恰相反:它首先查看webapp,然后转到父类加载器(Tomcat 6/7的"lib"和Tomcat 5.5的"共享").这个规则的例外是系统类(我认为所有包含java.*和javax.*的东西),这些类只在系统类加载器中查找.我相信他们这样做的原因是你说的第一个原因.

所以基本上可以实现父优先策略.实现parent-last也没问题.两种策略都有其缺点和优点.

我将再给你一个理由,为什么要实现parent-first:你减少了perm内存中加载的类的数量.想象一下,您有多个使用相同库的Web应用程序.使用parent-first将库加载一次.使用parent-last,它将被多次加载.
但是,对于父级优先,所有Web应用程序都需要使用相同版本的库,而使用parent-last时,它们可能使用不同的版本.


Bri*_*ach 4

并不真地。事实上,它就像实例化 anURLClassLoader并将其提供null给父级一样简单:

myClassLoader = new URLClassLoader(myUrlArray, null);
Run Code Online (Sandbox Code Playgroud)

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