【发布时间】:2021-05-29 01:10:49
【问题描述】:
首先,我知道以前有人问过这个问题,但我见过的解决方案都没有为我工作!
为了能够用新的字节码覆盖类的现有实现,我想要一个类加载器(设置为默认值),其中对任何类的所有调用(不包括像“java”这样的 java 包)都通过我的 loadClass/findClass 被覆盖方法。从那里我可以检查静态注册表以查看该类是否有覆盖。我愿意尝试以不同的方式执行此操作,但到目前为止,这似乎是最快、最简单的解决方案。
我的问题是,出于某种原因,即使我在 VM args(-Djava.system.class.loader=my.package.path.ProxyClassLoader) 中将加载器设置为默认值,它也会将加载(类)抛给父级,然后我假设将类加载器设置为自身。这意味着所有查找或加载类的调用现在都通过父类而不是我的类加载器。
另外,我想使用 JUnit 来测试它,但我无法让它使用自定义类加载器(在 gradle 中使用带有 JUnit 引擎的 JUnit API)所以我刚上老学校并使用了 main(我在哪里可以修饰 vm 参数)。
我尝试过的事情:
- 将类加载器设置为线程上下文加载器。
- 重写 loadclass 以尽量不将负载交给父级,这导致的问题比解决的问题多得多。
- 尝试进行反射以更改类的类加载器(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);
}
}
谢谢!
【问题讨论】:
标签: java classloader bytecode