我们的Java应用程序依赖于网络共享上可用的一些资源。此网络共享位于类路径中,并且在运行时使用MyClass.class.getResourceAsStream("/myfile.jpg")
读取资源。如何从java classpath中的网络目录正确加载资源?
java -Djava.class.path=\\myserver\myshare:C:\myjar.jar MainClass
当共享在启动时可用时,一切都运行顺利。位于共享中的图像和属性文件可以使用getResourceAsStream()
来读取。但是,如果股票不在线应用程序启动时,即使份额联机读取之前的任何资源,它们不能使用getResourceAsStream()
读取。
否则使用eclispse +反编译一些挖,我注意到一个区别。默认类加载器继承自URLClassLoader,其成员(URLClassPath
)包含URLClassPath.Loader
实例的列表。在第一种情况下,它包含URLClassPath.FileLoader
和URLClassPath.JarLoader
。在第二种情况下,它只包含一个jar加载器。
这就像Java的确定类路径条目是无效的,并完全放弃它。
这是为什么?我怎样才能避免它?
更新 我无法改变,使我们加载的,因为几个原因资源的机制:
- 有目前加载文件这样对我的改变有太多的领域此刻
- 在有些情况下由资源实际上是由一个第三方组件
装我没有问题,创建自定义的类装载器的情况下,我只需要一些指导如何做到这一点。
我想这个问题,但未能获得预期的结果:
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
[email protected]
[email protected]
[email protected]
所以正在创建我的类加载器,并且正在调用load类,但它似乎不是它正在加载的类的类加载器?
最安全的办法大概是写自己的类加载器。这意味着你完全控制。 – biziclop
我会如何去做这个简单的情况?到目前为止,我所见过的所有资源似乎都在运行时用于按名称加载类(例如,Class.forName(“string”))。我宁愿不必每次调用'getResourceAsStream()'手动创建一个新的类加载器并调用它。 – Travis
为什么不能使用File和FileInputStream来访问文件? – pauli