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

| Java中的类加载器的正确行为是: 如果已经加载,则返回该类 调用父loadClass() 尝试并加载类本身。 因此,应始终首先加载系统类路径中定义的类。 Tomcat每次战争都定义了类加载器,该类加载器将系统类加载器作为父类,因此,如果您尝试加载一个类,它将首先在系统类路径中查找,然后在war文件中定义的类路径中查找。 根据我的理解,这有两个原因: 为了避免使用不同版本的类而出现问题。想象一下,我在战争中重新定义了java.lang.Object,那将是一场噩梦。 为了避免依赖于子类加载器:系统类加载器不能依赖子类加载器:例如,很难重新部署战争。 因此,问题是: 除了上述问题之外,实现不首先进行父搜索的类加载器是否还有其他陷阱?     
已邀请:
Tomcat不会首先查找父类加载器。实际上,它的作用恰恰相反:它首先在Web应用程序中查找,然后才转到父类加载器(对于Tomcat 6/7,它是\“ lib \”,对于Tomcat 5.5是\“ shared \”)。该规则的例外是系统类(我认为所有具有java。*和javax。*包的软件包),这些类仅在系统类加载器中查找。我相信他们这样做的原因是您所说的#1原因。 因此,基本上可以实施“家长优先”策略。也可以实现后代父项。两种策略各有利弊。 我再给您一个理由,为什么要先执行父级:减少烫发内存中加载的类数量。假设您有使用同一库的多个Web应用程序。使用父优先级,该库将被加载一次。使用parent-last,它将被多次加载。 但是,首先使用父级,则所有Web应用程序都必须使用相同版本的库,而使用父子级,则它们可能使用不同版本。     
并不是的。实际上,它就像实例化一个
URLClassLoader
并为父级赋予giving1 simple一样简单:
myClassLoader = new URLClassLoader(myUrlArray, null);
http://download.oracle.com/javase/6/docs/api/java/net/URLClassLoader.html     
我能想到的唯一其他原因是确保类路径按预期工作。首先搜索父级,实际上是将父级的类路径(即系统classpath)放在子级的类路径之前。因此,如果在使用-cp启动jvm时指定了特定的jar,它们将“阴影”您试图加载的任何存档中包含的所有jar。如果您不先检查父级,则子级的类路径将遮盖父级。     
Tarlog是正确的,您不必那样做。 Java没有预见到像tomcat这样的用例。 但是,为什么容器在一个VM中托管多个应用程序是一个问题。单独的流程更好。     
如果根本不搜索父对象,则将无法访问所有标准Java对象,并且可能根本无法运行。 但是在尝试使用父类之前先搜索自己的类加载器是合理的。如果要覆盖上面的类提供的行为,则需要以这种方式进行。 JVM没有,因为首先搜索您的父级是最有意义的。但是,如果您知道自己在做什么,则可以使用类加载器来做一些非常有趣的事情。看看Classworlds。     
Tomcat Web应用程序类加载器不遵循“先使用父级”。如文档中所述:   如上所述,Web应用程序类加载器不同于默认的Java委托模型(根据Servlet规范2.4版的建议,第9.7.2节Web应用类加载器)。处理从Web应用程序的WebappX类加载器加载类的请求时,该类加载器将首先在本地存储库中查找,而不是在查找之前委派。也有例外。属于JRE基类的类不能被覆盖。     

要回复问题请先登录注册