Наше 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 определяет, что запись classpath недействительна, и полностью ее отбрасывает.
Почему это? Как я могу избежать этого?
Обновление
Я не могу изменить механизм загрузки ресурсов по нескольким причинам:
- Слишком много областей, в которых в данный момент загружаются файлы, поэтому я могу изменить в данный момент
- Существуют ситуации, когда ресурс фактически загружается сторонним компонентом
У меня нет проблем с созданием пользовательского загрузчика классов, мне просто нужно несколько советов, как это сделать.
Я пытался с этим, но не смог получить ожидаемый результат:
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
Итак, мой загрузчик классов создается и вызывается класс загрузки, но он не является загрузчиком классов для загружаемых классов?