4 Stimmen

Wie lade ich Ressourcen aus einem Netzwerkverzeichnis korrekt in den Java-Klassenpfad?

Unsere Java-Anwendung ist auf einige Ressourcen angewiesen, die auf einer Netzwerkfreigabe verfügbar sind. Diese Netzwerkfreigabe befindet sich auf dem Klassenpfad, und die Ressourcen werden zur Laufzeit mit MyClass.class.getResourceAsStream("/myfile.jpg") .

java -Djava.class.path=\\myserver\myshare:C:\myjar.jar MainClass

Wenn die Freigabe beim Starten verfügbar ist, läuft alles reibungslos. Bild- und Eigenschaftsdateien, die sich in der Freigabe befinden, können gelesen werden mit getResourceAsStream() . Wenn die Aktie jedoch nicht online ist, wenn die Anwendung gestartet wird, auch wenn die Aktie online geht, bevor irgendwelche Ressourcen gelesen werden können sie nicht gelesen werden mit getResourceAsStream() .

Bei meinen Recherchen mit eclispse + decompiler habe ich einen Unterschied festgestellt. Der Standard-Classloader erbt von URLClassLoader, und seine ucp Mitglied ( URLClassPath ) enthält eine Liste von URLClassPath.Loader Instanzen. Im ersten Szenario enthält sie eine URLClassPath.FileLoader und eine URLClassPath.JarLoader . Im zweiten Szenario enthält es nur einen Jar-Loader.

Es ist, als ob Java feststellt, dass der Klassenpfadeintrag ungültig ist und ihn komplett verwirft.

Warum ist das so? Wie kann ich es vermeiden?

Update Ich kann den Mechanismus, mit dem wir die Ressourcen laden, aus mehreren Gründen nicht ändern:

  1. Es gibt viel zu viele Bereiche, in denen Dateien auf diese Weise geladen werden, als dass ich derzeit etwas ändern könnte
  2. Es gibt Situationen, in denen die Ressource tatsächlich von einer Komponente eines Dritten geladen wird

Ich habe kein Problem damit, einen benutzerdefinierten Klassenlader zu erstellen, ich brauche nur eine Anleitung, wie ich es machen soll.

Ich habe es damit versucht, konnte aber nicht die erwarteten Ergebnisse erzielen:

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());
    }
}

Wenn ich laufe java -cp . -Djava.system.class.loader=MyUrlClassLoader ClassLoaderMain

Diese Ausgaben:

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

So meine Klasse Loader erstellt wird, und Klasse laden wird aufgerufen, aber es scheint nicht zu sein, die Klasse Loader für die Klassen, die es lädt?

1voto

Travis Punkte 2634

Ich habe das Problem schließlich gelöst, indem ich meine eigene ClassLoader die von URLClassLoader abgeleitet ist.

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

public class CustomClassLoader extends URLClassLoader {

    public CustomClassLoader(ClassLoader parent) {
        // System classloader will filter inaccessible URLs. 
        // Force null parent to avoid using system classloader.
        super(createURLReferences(), null);
    }

    /**
     * Build an array of URLs based on the java.class.path property.
     * @return An array of urls to search for classes.
     */
    private static URL[] createURLReferences() {
        String classpath = System.getProperty("java.class.path");
        String[] classpathEntries = classpath.split(System.getProperty("path.separator"));
        List<URL> urls = new ArrayList<URL>();
        for (String classpathEntry : classpathEntries) {
            File classpathFile = new File(classpathEntry);
            URI uri = classpathFile.toURI();
            try {
                URL url = uri.toURL();
                urls.add(url);
            } catch (MalformedURLException e) {
                System.out.println("Ignoring classpath entry: " + classpathEntry);
            }
        }

        return urls.toArray(new URL[urls.size()]);
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X