首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使javagent使用Java中的系统类加载器<9

使javagent使用Java中的系统类加载器<9
EN

Stack Overflow用户
提问于 2020-06-06 17:48:16
回答 1查看 408关注 0票数 2

我有一个java-agent,它依赖于一些依赖库。我们有一个定制的类加载器,它不执行全局绑定,并提供确定性的类加载,并通过-Djava.system.class.loader=指定。然而,java代理类似乎仍然是通过AppClassLoader加载的,导致了一些ClassNotFoundException,在这上面浪费了几个小时后,我偶然发现了这个JDK bug,它概述了这个问题,现在已经关闭,但修复只针对JDK 9+。

我想知道在Java中是否有一种方法可以强制java- <=8类由指定的类加载器加载。

定制的类加载器看起来像这样,

代码语言:javascript
复制
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实际上是由自定义的类加载器加载的。

EN

回答 1

Stack Overflow用户

发布于 2020-06-07 20:08:51

JDK8和JDK的不同之处在于,JDK8将-javaagent 9+添加到系统类路径中,而JDK 9+则调用自定义ClassLoader的appendToClassPathForInstrumentation

因此,在JDK8中,如果在尝试查找类本身之前将自定义ClassLoader委托给父ClassLoader (即系统类加载器),则代理将由系统类加载器加载。为了解决这个问题,您的自定义ClassLoader可能会颠倒委托顺序:首先尝试查找类本身,然后委托给父类。

例如,可以通过覆盖loadClass方法来实现,如下所示:

代码语言:javascript
复制
@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);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62229975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档