getResourceAsStream无法加载资源

3

我目前正在处理的项目使用了一个包含在.jar文件中的旧应用程序。该应用程序的职责之一是在配置文件发生更改时更新数据库。每次我尝试运行这个文件(它是一个简单的Ant任务扩展),都会在进程早期抛出异常。我反编译了负责的Java文件,并发现抛出异常的位置在这里。我不知道问题出在哪里,因为“hibernate.cfg.xml”与抛出异常的.class文件包含在同一个.jar文件中。

ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream in = loader.getResourceAsStream("hibernate.cfg.xml");
if (in == null) {
  throw new RuntimeException("Couldn't find built in hibernate config");
}

如果有人有任何想法,甚至只是指引我方向,我将不胜感激。
当然,任何解决方案都必须是外部的,因为客户已经在生产环境中使用了这个程序版本。
5个回答

3
你是从根目录加载它吗?你需要使用“/hibernate.cfg.xml”而不是仅使用“hibernate.cfg.xml”吗?

可以实现,问题在于我无法更改其中的内容,因为这个.jar文件已经在使用中,我也没有官方源代码的访问权限(只有我手动反编译的代码)。 - Michal Gorecki
1
那没关系。使用上下文类加载器时,路径始终相对于类路径根目录。 - BalusC
我认为这是问题所在。个人建议在jar包内的类文件上执行<<Class>/getClass()>.getResourceAsStream("/hibernate.cfg.xml")。 - Chris Dennett
如果你不能停止它并改变内部内容,那么修复将会很困难。你需要在运行时修改字节码(使用像BTrace这样的工具),但除非这是唯一的方法,否则我不建议这样做。 - Jeff Storey

2

getResourceAsStream()方法要求文件与类加载器的原始类在同一个包中。请确认您的文件是否在正确的包中?

哎呀,抱歉,我没有完全阅读问题。请忽略此消息。


他正在使用上下文类加载器,而不是类的类加载器。因此这不是问题的原因。 - BalusC
不是这样的。也就是说,该文件位于 .jar 文件的根目录下。文件如下: /company/dir/dir/problem.class 和 /hibernate.cfg.xml我不确定这是否会有所区别,但不幸的是这是我无法更改的遗留代码。 - Michal Gorecki

1

尝试

InputStream in = YourClass.class..getResourceAsStream("hibernate.cfg.xml");

如果类和cfg文件在同一个jar包中,这将起作用。

编辑: 如果您无法重新构建应用程序,则需要将jar包添加到引导类加载器中。这很丑陋。 您可以通过使用以下命令运行jvm来实现(请尝试使用确切的参数,您可能还需要将jre中的rt.jar添加到其中)。

-Xbootclasspath your.jar

你的问题在于代码正在使用加载Thread类的类加载器,这很可能是引导类加载器。而且你现在处于一个更复杂的环境(应用服务器?),它使用不同的类加载器来加载你的jar包。因此,引导类加载器找不到你的资源。

1
不幸的是,那并没有帮助到我。但是,我确实学到了一些关于Xbootclasspath的知识,所以谢谢! - Michal Gorecki

0

有可能类加载器无法打开包含在jar文件中的文件。请尝试以下两种方法之一:1)尝试提取jar文件并从文件系统中运行它;2)如果jar清单中有ClassPath条目,则尝试将hibernate.cfg.xml提取到类路径中的一个目录中,并查看是否可以运行。


0

显然,hibernate.cfg.xml文件不在JAR文件的源根目录中,而是放置在一个包内。您需要在资源名称中指定包路径。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接