Tuesday, November 18, 2008

a few notes about the Java ClassLoader

I found a case today where the clazz.getResourceAsStream(String) retrieved a resource but the clazz.getClassLoader.getResourceAsStream(String) failed to find it. Weird.

I never figured it out, but I came up with the following as I tried:

  • There is no way to get all the entire path that is being searched. I always come to this point and try, but it's a hard fact of Java. I did find this blog entry that explained how you might patch the ClassLoader.toString() methods. But read on...
  • Even for URLClassLoader classes, it looks like it'll search through directories that are not found by the getURL() method (so that previous blog entry won't catch them all). I found this by running some unit tests in Maven with the method that follows, and it was retrieving things from the 'classes' and 'test-classes' directories that didn't show in the getURL() results.
  • If you try a call to getResource(""), it'll show some of the directory paths that are in the search path. I don't know for sure that this is true because I can't find it documented, but it seems to work. So the following method will show all the URL and path resources up the line from a given loader:

private static void showAllResourcePaths(ClassLoader loader) {
try {
String indent = "";
for (ClassLoader nextLoader = loader; nextLoader != null; nextLoader = nextLoader.getParent()) {
System.out.println(indent + " loader " + nextLoader);
for (Enumeration<URL> urls = nextLoader.getResources(""); urls.hasMoreElements(); ) {
URL url = urls.nextElement();
System.out.println(indent + " path: " + url);
}
if (nextLoader instanceof URLClassLoader) {
System.out.println(indent + " URLs: " + Arrays.asList(((URLClassLoader) nextLoader).getURLs()));
}
indent += "-";
}
} catch (Exception e) {
e.printStackTrace();
}
}

  • Using that method will show you most of what you want because, in my tests, all the class loaders in the ancestry turned out to be URLClassLoaders.

What is the difference between the clazz.getResource and clazz.getClassLoader().getResource methods?

No comments: