web-dev-qa-db-ja.com

実行時にディレクトリをクラスパスに追加できますか?

Javaでの動作をよりよく理解するために、実行時にディレクトリをクラスパスに動的に追加できるかどうかを知りたいです。

たとえば、"Java -jar mycp.jar"を使用して。jarを起動し、Java.class.pathプロパティを出力すると、得るかもしれない:

Java.class.path: '.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/Java'

実行時にこのクラスパスを変更して、別のディレクトリを追加できますか? (たとえば、追加したいディレクトリにある。jarを使用してクラスを最初に呼び出す前に)。

34
Cedric Martin

次の方法を使用できます。

URLClassLoader.addURL(URL url)

ただし、メソッドはprotectedであるため、リフレクションを使用してこれを行う必要があります。

public static void addPath(String s) throws Exception {
    File f = new File(s);
    URL u = f.toURL();
    URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class urlClass = URLClassLoader.class;
    Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
    method.setAccessible(true);
    method.invoke(urlClassLoader, new Object[]{u});
}

Java Trail on Reflection を参照してください。特にセクションReflectionsの欠点

48

2014年の更新:これは、2011年にJonathan Spoonerによって承認された回答のコードで、Eclipseのバリデーターが警告(非推奨、rawtypes)を作成しないように少し書き直されました

//need to do add path to Classpath with reflection since the URLClassLoader.addURL(URL url) method is protected:
public static void addPath(String s) throws Exception {
    File f = new File(s);
    URI u = f.toURI();
    URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class<URLClassLoader> urlClass = URLClassLoader.class;
    Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
    method.setAccessible(true);
    method.invoke(urlClassLoader, new Object[]{u.toURL()});
}
24
knb

はい、URLClassLoaderを使用できます。例 ここ を参照してください。リフレクションを使用しません。

-編集-

推奨されるリンクからの例のコピー。

import javax.naming.*;
import Java.util.Hashtable;
import Java.net.URLClassLoader;
import Java.net.URL;
import Java.net.MalformedURLException;

public class ChangeLoader {

    public static void main(String[] args) throws MalformedURLException {
    if (args.length != 1) {
        System.err.println("usage: Java ChangeLoader codebase_url");
        System.exit(-1);
    }

    String url = args[0];
    ClassLoader prevCl = Thread.currentThread().getContextClassLoader();

    // Create class loader using given codebase
    // Use prevCl as parent to maintain current visibility
    ClassLoader urlCl = URLClassLoader.newInstance(new URL[]{new URL(url)}, prevCl);

        try {
        // Save class loader so that we can restore later
            Thread.currentThread().setContextClassLoader(urlCl);

        // Expect that environment properties are in
        // application resource file found at "url"
        Context ctx = new InitialContext();

        System.out.println(ctx.lookup("tutorial/report.txt"));

        // Close context when no longer needed
        ctx.close();
    } catch (NamingException e) {
        e.printStackTrace();
        } finally {
            // Restore
            Thread.currentThread().setContextClassLoader(prevCl);
        }
    }
}
12
Kashyap