从.war文件加载类的顺序

Syn*_*r0r 14 java web-applications classloader

我有一个关于保证的问题,如果有的话,在下面的场景中(请注意问题不是"如何以不同的方式做到这一点?"),问题实际上是关于以下情况下的类加载顺序(至更好地理解类加载的工作原理).

这是假设的场景......有一个.war文件,它具有以下(部分)目录结构:

 WEB-INF/classes/com/acme/Bunny.class
 .
 .
 .
 WEB-INF/lib/acme.jar
Run Code Online (Sandbox Code Playgroud)

两个Bunny.class文件都有导入引用acme.jar中的其他类

Bunny.classWEB-INF /班/ ...是具有相同的名称/路径,一个类从唯一的类acme.jar.

的.jar文件acme.jar还包含com.acme.Bunny(也有使用没有特殊的类装载器的技巧).

我知道Java规范保证在程序实际使用(或者故意"手动加载")之前不会加载类,这就是为什么如果你填充成千上万的.jar,比如说.war,类加载器不会开始类加载数万个类.

(编辑)

但是上面示例中的两个类的加载顺序又如何呢?

应该措辞:

但是如何确定上面两个类中的哪一个被加载?

或类似的东西 :)

有做一个保证:com.acme.Bunny不得将任何其它类之前,使用com.acme ....

基本上,在维基百科上,写了以下内容:

最复杂的JAR地狱问题出现在利用类加载系统的完全复杂性的情况下.Java程序不需要仅使用单个"平面"类加载器,而是可以由几个(或实际上是无限数量)嵌套的协作类加载器组成.由不同类加载器加载的类可能以复杂的方式进行交互,而开发人员无法完全理解这些类,从而导致无法解释的错误或错误.

所以我想知道:我可以确定/classes/com/acme/Bunny.class是否会在WEB-INF/lib / dir中的.jar之前进行类加载?

Saj*_*eev 14

选择的答案是错误的.Servlet规范版本2.4和3.0明确指出首先加载WEB-INF /类,然后加载WEB-INF/lib

Servlet 2.4:http://download.oracle.com/otn-pub/jcp/servlet-2.4-fr-spec-oth-JSpec/servlet-2_4-fr-spec.pdf - 第SRV.9.5节,最后一段

Servlet 3.0:http://download.oracle.com/otn-pub/jcp/servlet-3.0-fr-oth-JSpec/servlet-3_0-final-spec.pdf - 第10.5节,最后一段

Web应用程序类加载器必须首先从WEB-INF/classes目录加载类,然后从WEB-INF/lib目录中的库JAR加载类.


Cam*_*ner 8

这个问题可能会有所帮助.

servlet规范对此很模糊.人们期望在"WEB-INF/lib"之前搜索"WEB-INF/classes",但似乎需要由servlet容器来决定.您可以确定的是,容器应该始终先加载一个容器,因此您永远不应该在同一个容器中看到这两个类.搜索路径可以是可配置的,具体取决于您的容器.

对不起,我不能更具体:欢迎来到多个servlet容器的世界.不要让我开始使用Websphere的趣味游戏.

  • [servlet 2.4 spec](http://download.oracle.com/otn-pub/jcp/servlet-2.4-fr-spec-oth-JSpec/servlet-2_4-fr-spec.pdf)说:"网络应用程序类加载器必须首先从WEB-INF/classes目录加载类,然后从WEB-INF/lib目录中的库JAR加载." 类似于Servlet 3.0. (11认同)
  • @Cameron Skinner请你编辑正确的答案. (4认同)

Lau*_*ves 0

您似乎混淆了“之前”的两种不同含义。

类按照使用的顺序加载。这是时间性的,是“before”更正确的用法。如果 Foo 在 Bar 之前使用,那么它将在 Bar 之前加载。

您还讨论了classes/com/acme/Bunny.class是否会在acme.jar的com/acme/Bunny.class“之前”加载。第二个根本不会被加载。类加载器将在类路径上查找 com/acme/Bunny.class 的第一个实例,在类中找到该实例,然后停止查找。