簡體   English   中英

使 javagent 在 Java < 9 中使用系統類加載器

[英]Make javagent use system classloader in Java < 9

我有一個依賴於一些依賴庫的 java-agent。 我們有一個自定義的類加載器,它不進行 globbing 並提供確定性的 class 加載,並通過-Djava.system.class.loader=指定。 但是,似乎 java-agent 類仍在通過 AppClassLoader 加載,導致一些ClassNotFoundException 在這浪費了幾個小時之后,我遇到了這個JDK 錯誤,它概述了這個確切的問題,現在已經關閉,但只對 JDK 9+ 進行了修復。

我想知道 Java <=8 中是否有辦法強制指定的類加載器加載 java-agent 類。

自定義 class 加載程序看起來像這樣,

public class CustomClassloader extends URLClassLoader{ 

    public CustomClassloader(ClassLoader parent) throws Exception {
         //getJarPaths has the path of the java-agent jar as well as
         //all dependency jar it needs.
        super(getJarPaths(), parent);
    }


    private static URL[] getJarPaths() throws Exception {
       //custom implementation
    }


    public void appendToClassPathForInstrumentation(String path) throws   MalformedURLException {
        assert(Thread.holdsLock(this));
        super.addURL(Paths.get(path).toUri().toURL());
    }
}

上面的類加載器與JDK9+完美配合,javaagent實際上是由自定義類加載器加載的。

JDK 8 和 JDK 9+ 的區別在於,JDK 8 在系統 class 路徑中添加了-javaagent jar,而 JDK 9+ 則調用了自定義 ClassLoader 的appendToClassPathForInstrumentation

因此,在 JDK 8 中,如果您的自定義 ClassLoader 在嘗試查找 class 本身之前委托給父 ClassLoader(即系統 class 加載程序),則代理將由系統 ZA2F2ED4F8EBC2CBB4C21A29DC40ABC 加載。 為了解決這個問題,您的自定義 ClassLoader 可能會反轉委托順序:首先嘗試找到 class 本身,然后委托給父級。

例如,這可以通過重寫loadClass方法來完成,如下所示:

@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    synchronized (getClassLoadingLock(name)) {
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            try {
                c = findClass(name);
            } catch (ClassNotFoundException e) {
                c = super.loadClass(name, false);
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

@Override
public URL getResource(String name) {
    URL url = findResource(name);
    if (url != null) {
        return url;
    }
    return super.getResource(name);
}

@Override
public Enumeration<URL> getResources(String name) throws IOException {
    List<URL> urls = Collections.list(findResources(name));
    urls.addAll(Collections.list(getParent().getResources(name)));
    return Collections.enumeration(urls);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM