我们的Java应用程序依赖于一些位于网络共享上的资源。这个网络共享位于类路径上,资源在运行时使用MyClass.class.getResourceAsStream("/myfile.jpg")
读取。
java -Djava.class.path=\\myserver\myshare:C:\myjar.jar MainClass
当共享文件在启动时可用时,一切都运行顺利。位于共享文件中的图像和属性文件可以使用
getResourceAsStream()
读取。然而,如果应用程序启动时共享不在线上,即使在读取任何资源之前共享上线,也无法使用getResourceAsStream()
读取它们。通过使用eclispse +反编译器进行一些挖掘,我注意到一个区别。默认的类加载器继承自URLClassLoader,并且其
ucp
成员(URLClassPath
)包含URLClassPath.Loader
实例列表。在第一种情况下,它包含一个URLClassPath.FileLoader
和一个URLClassPath.JarLoader
。在第二种情况下,它只包含一个jar加载器。就好像Java确定了类路径条目是无效的并完全舍弃了它。
为什么会这样?我该如何避免?
更新: 由于以下原因,我无法更改我们正在加载资源的机制:
1. 目前有太多区域以这种方式加载文件,我暂时无法更改 2. 有些情况下,资源实际上是由第三方组件加载的
我没有问题创建自定义类加载器,我只需要一些指导。
我尝试过这个,但无法获得预期的结果:
import java.net.URL;
import java.net.URLClassLoader;
public class MyUrlClassLoader extends URLClassLoader {
public MyUrlClassLoader(ClassLoader parent) {
super(new URL[0], parent);
System.out.println("MyUrlClassLoader ctor");
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
System.out.println("url find class " + name);
return super.findClass(name);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("url load class " + name);
return super.loadClass(name);
}
@Override
public URL getResource(String name) {
System.out.println("url get resource " + name);
return super.getResource(name);
}
}
import java.net.URL;
public class ClassLoaderMain {
public static void main(String[] args) throws ClassNotFoundException {
URL url = ClassLoaderMain.class.getResource("/myfile.txt");
System.out.print("Loaded? ");
System.out.println(url != null);
System.out.println(ClassLoaderMain.class.getClassLoader().toString());
System.out.println(MyUrlClassLoader.class.getClassLoader().toString());
System.out.println(FakeClass.class.getClassLoader().toString());
}
}
当我运行
java -cp . -Djava.system.class.loader=MyUrlClassLoader ClassLoaderMain
时,会输出:
MyUrlClassLoader ctor
url load class java.lang.System
url load class java.nio.charset.Charset
url load class java.lang.String
url load class ClassLoaderMain
Loaded? true
sun.misc.Launcher$AppClassLoader@923e30
sun.misc.Launcher$AppClassLoader@923e30
sun.misc.Launcher$AppClassLoader@923e30
我的类加载器正在创建,load class方法被调用,但它似乎不是加载所需类的类加载器?