有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用自定义类加载器重写类的现有实现

首先,我知道以前有人问过这个问题,但我所看到的解决方案都不适合我

为了能够用新字节码覆盖类的现有实现,我需要一个类加载器(设置为默认值),其中所有对任何类的调用(不包括像“java”这样的java包)检查我的loadClass/findClass重写方法。从那里,我可以检查静态注册表,看看是否有该类的重写。我愿意尝试不同的方法,但到目前为止,这似乎是最快、最简单的解决方案

我的问题是,出于某种原因,即使我在VM args(-Djava.system.class.loader=my.package.path.ProxyClassLoader)中将我的装入器设置为默认值,它也会将(类的)装入抛出到父级,然后我假设父级会将类装入器设置为自身。这意味着所有查找或加载类的调用现在都通过父类而不是我的类加载器

另外,我想使用JUnit来测试这个,但是我无法让它使用定制的类加载器(在gradle中使用JUnitAPI和JUnit引擎),所以我只是去了老学校,使用了一个main(在那里我可以修改vm参数)

我尝试过的事情:

  1. 将类加载器设置为线程上下文加载器
  2. 重写loadclass以尝试不向父级抛出加载,这只会导致比解决问题多得多的问题
  3. 尝试进行反射以更改类的类加载器(Java+特别不允许这样做,这将非常缓慢,而且不值得)

这是我的类加载器原样:

public class ProxyClassLoader extends ClassLoader {
    public ProxyClassLoader(ClassLoader parent) {
        super(parent);
        Thread.currentThread().setContextClassLoader(this);

    }

    //Didn't look like i need to override anything so 
    //this is just a simplicity thing for me(i call it through other classes)
    public Class<?> defineClass(byte[] b, String name) {
        return super.defineClass(name, b, 0, b.length, defaultDomain);
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        if (ClassManager.hasOverload(name)) return ClassManager.retrieve(name);
        return super.loadClass(name, resolve);

    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        return this.loadClass(name, true);
    }
}

谢谢


共 (1) 个答案

  1. # 1 楼答案

    不要完全跳过超级类装入器。试试这样的吗

     @Override protected Class<?> loadClass(String name, boolean resolve) throws 
         ClassNotFoundException {
                if(name belongs to java classes) {
                     return super.loadClass(name, resolve);
                }
                byte[] b = ..// read bytes from your .class files. or use getResourceAsStream(name)
                Class<?> c = defineClass(b, name);
                if(resolve) resolveClass(c);
                return c;
            }