Загрузчик классов работает только с classpath, а не с URL

#java #classloader

#java #classloader

Вопрос:

Итак, я пытаюсь загрузить файл по ссылке и запустить его в памяти. Все работает, работает нормально, но только тогда, когда файл .jar находится в classpath проекта. Мой код выглядит следующим образом:

 import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.JarInputStream;

public class Main {

    public static URL getURL(String string) throws MalformedURLException {
        try {
            return new URL(string);
        } catch (MalformedURLException x) { return new URL("file:"   string); }
    }

    public static void main(String args[]) throws Exception {

        String jarLocation = "http://www.google.ca/file.jar";
        URL url = new URL(jarLocation);
        getURL(jarLocation);
        JarInputStream jis = new JarInputStream(url.openStream());
        String main = jis.getManifest().getMainAttributes().getValue("Main-Class");
        String classpaths[] = jis.getManifest().getMainAttributes().getValue("Class-Path").split(" ");
        for (String classpath: classpaths) {
            getURL(classpath);
        }
        URLClassLoader loader = new URLClassLoader((new URL[0]));
        Class<?> cls = loader.loadClass(main);
        Thread.currentThread().setContextClassLoader(loader);
        Method m = cls.getMethod("main", new Class[]{new String[0].getClass()});
        m.invoke(null, new Object[]{args});

    }

}
  

Проблема в том, что независимо от того, что это за ссылка, .jar будет запускаться, только если она находится в classpath проекта. Как я могу загрузить файл по ссылке, а не из наличия его в classpath?

Ответ №1:

Это потому, что вы не передаете свои URL-адреса .jar в URLClassLoader. В вашем коде он принимает пустой массив, поэтому я не знаю, как загружать классы из вашего jar-файла.

Вот пример того, как вы можете изменить свой код, чтобы передавать URL-адреса jar в URLClassLoader:

 public class Main {

    public static URL getURL(String string) throws MalformedURLException {
        try {
            return new URL(string);
        } catch (MalformedURLException x) { return new URL("file:"   string); }
    }

    public static void main(String args[]) throws Exception {

        String jarLocation = "http://www.google.ca/file.jar";
        List<URL> urls = new ArrayList<>();
        URL url = new URL(jarLocation);
        urls.add(getURL(jarLocation));
        JarInputStream jis = new JarInputStream(url.openStream());
        String main = jis.getManifest().getMainAttributes().getValue("Main-Class");
        String classpaths[] = jis.getManifest().getMainAttributes().getValue("Class-Path").split(" ");
        for (String classpath: classpaths) {
            urls.add(getURL(classpath));
        }
        URLClassLoader loader = new URLClassLoader(urls.toArray(new URL[urls.size()]));
        Class<?> cls = loader.loadClass(main);
        Thread.currentThread().setContextClassLoader(loader);
        Method m = cls.getMethod("main", new Class[]{new String[0].getClass()});
        m.invoke(null, new Object[]{args});

    }

}