Need help with strange Class#getResource() issue

2020-04-08 13:02发布

I have some legacy code that reads a configuration file from an existing jar, like:

URL url = SomeClass.class.getResource("/configuration.properties");
// some more code here using url variable
InputStream in = url.openStream();

Obviously it worked before but when I execute this code, the URL is valid but I get an IOException on the third line, saying it can't find the file. The url is something like "file:jar:c:/path/to/jar/somejar.jar!configuration.properties" so it doesn't look like a classpath issue - java knows pretty well where the file can be found..

The above code is part of an ant task and it fails while the task is executed.

Strange enough - I copied the code and the jar file into a separate class and it works as expected, the properties file is readable.

At some point I changed the code of the ant task to

URL url = SomeClass.class.getResource("/configuration.properties");
// some more code here using url variable
InputStream in = SomeClass.class.getResourceAsStream("/configuration.properties");

and now it works - just until it crashes in another class where a similiar access pattern is implemented..

Why could it have worked before, why does it fail now? The only difference I see at the moment is, that the old build was done with java 1.4 while I'm trying it with Java 6 now.

Workaround

Today I installed Java 1.4.2_19 on the build server and made ant to use it. To my totally frustrating surprise: The problem is gone. It looks to me, that java 1.4.2 can handle URLs of this type while Java 1.6 can't (at least in my context/environment).

I'm still hoping for an explanation although I'm facing the work to rewrite parts of the code to use Class#getRessourceAsStream which behaved much more stable...

标签: java ant
4条回答
淡お忘
2楼-- · 2020-04-08 13:23

It works with getresourceasstream because it is in the classpath, but it doesn't work with the URL maybe because the URL is not ok.

I don't know if the URL that getResource is creating is not ok, or there isn't a correct handler for the protocol (wouldn't it be file:jar:c:/myjar.jar!configuration.properties or something by the like (with two colons?)

查看更多
来,给爷笑一个
3楼-- · 2020-04-08 13:24

A typical implementation of ClassLoader.getResourceAsStream is:

public InputStream getResourceAsStream(String name) {
    URL url = getResource(name);
    try {
        return url != null ? url.openStream() : null;
    } catch (IOException e) {
        return null;
    }
}

Class.getResource and getResourceAsStream behave the same as each other.

So it looks like either you are using a strange and broken subclass of ClassLoader, or there is some mistake in the tests on your side.

查看更多
贪生不怕死
4楼-- · 2020-04-08 13:41

use urlConnection.setUseCaches(false), since it's an ant task, it's likely not to be forked in a separate process. The URLs cache the files (or the JarFile in that case)... if the files is change due to the build, you get quite a similar behavior.

you may want to close the modified jar files meanwhile useCaches(true), JarURLConnection.getJarFile().close()

Sometime I wish handling of Jar/Zip was a little better

cheers

查看更多
男人必须洒脱
5楼-- · 2020-04-08 13:44

There are bugs in several Java versions when using file URLs containing spaces. "/path/to/jar" is probably not your real path, so I at least assume that this is what you're running into. Your code is at least in theory ok.

查看更多
登录 后发表回答