2012-08-14 118 views
0

我正在使用工作程序JVM执行各种操作的应用程序服务器上工作。Jar文件自发地无法找到内部根资源

使用-cp开关启动worker jvms,并指定包含供应商库和其他重要功能的JAR文件。

我有一个非常有趣的问题,其中jar文件CLASSES加载和正确执行代码,但任何时候他们试图访问资源内的jar文件(具体与getResourceAsStream()方法),然后它吹起声称它不能找到它。我已经验证了这些资源肯定存在于正在加载的JAR中,事实上,如果我操纵JAR以在外部定位资源,它就可以工作。问题是这些都是专有的库,并没有与源代码,所以我陷入了瘫痪,我必须通过反编译和方法入口断点来做所有事情。

也许最奇怪的部分是这些库已经改变了很多个月,并且一直在其他(包括生产)应用服务器上工作。

他们是JRE 1.6.0_17

所以我的问题是

  • 为什么会用-cp条目的JVM能够从罐子里装载类而不是资源
  • 做任何事情在这个领域从JRE 1.6.0_06变为1.6.0_17(这已经在最近发生了变化)

为了阐明,在JAR结构中,这些资源在jar的根上,即:

resource.prop 
META-INF/Manifest 
package/package/class.class 

JAR本身在加载时显然位于类路径中。 但是,所有以下决心空的(是的,这是推动我坚果所以我没有真正尝试所有3):

Jarclass.getClassLoader().getResourceAsStream("./resource.prop"); 
Jarclass.getClassLoader().getResourceAsStream("/resource.prop"); 
Jarclass.getClassLoader().getResourceAsStream("resource.prop"); 

这类似于Can't access resource in a JAR on all computers但没有解决这个问题。

+0

,想到的唯一的事情是:JAR的可使用依赖于一些奇怪的行为在JRE实现自定义的类装载器(写一个类加载器是不平凡的)。问题一般局限于一家供应商的图书馆吗?如果你使用Jarclass.getClassLoader()。toString(),它是否表明这不是由JRE创建的ClassLoader? – Durandal 2012-08-14 17:24:49

+0

令人难以置信的富有洞察力的评论预测了我在我的原始文章中甚至没有提到的东西。你是绝对正确的,有一个供应商正在使用自定义类加载器,并且它正在重载JRE标准类加载器,特别是加载资源。我的所有图书馆都没有改变,但我没想过要检查其他包含更改的类加载器的库。我研究了它,发现这是问题 - 供应商在对自定义类加载器所做的更改中犯了错误。谢谢! – 2012-08-15 18:15:46

回答

0

您是否检查过JAR中的manifest.mf文件?这是控制用于加载JAR内部资源的类路径的最简单的方式之一。

从JAR读取资源只与用于加载JAR的类路径部分相关。对于类文件,JAR中的文件夹结构足以让类加载器加载类,基本上是[CLASSPATH]/[Package]/[Classname]。

对于资源来说,这是另一回事。 JAR的根目录被添加到CLASSPATH而不是任何子目录,所以如果“resource.prop”在jar的根目录下,你提供的三个例子中的任何一个都可以工作。既然你说他们已经在罐子的根部,它只会加深这个谜团。

JAR是否发生了变化,就像旧版本一样工作,而新版本没有?

最近更改了您的应用服务器的CLASSPATH设置吗?我们遇到了IBM的WebSphere Application Server问题,我们必须将类加载器的规则设置为'最后一个父'(至少如果我的内存不会让我失败),那么它将首先使用来自JVM实例的Classpath,然后使用WebSphere的类加载器,因为我们加载了log4j。比IBM开始在更新版本的WebSphere中包含的那个版本旧的jar。

另一种选择是扩大JAR,更新MANIFEST.MF文件,以包括对性能绝对引用,然后将文件重新压缩到一个定制版本。

0

检查显示目录的名称在非工作罐放置。当我的应用程序被复制到目录中时,我遇到了类似的问题,其名称中的符号为!%