Java类装入器可以重写系统类的字节码(只有它们的副本)吗?JavaAgent类文件变压器类加载器未解决的问题
所以我有一个类加载器(MyClassLoader),它在内存中维护一组“特殊”类。这些特殊类是动态编译的,并存储在 MyClassLoader 中的字节数组中。当要求 MyClassLoader 输入类时,它首先检查其字典是否包含该类,然后再委派给 System 类装入器。它看起来像这样:specialClasses
class MyClassLoader extends ClassLoader {
Map<String, byte[]> specialClasses;
public MyClassLoader(Map<String, byte[]> sb) {
this.specialClasses = sb;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (specialClasses.containsKey(name)) return findClass(name);
else return super.loadClass(name);
}
@Override
public Class findClass(String name) {
byte[] b = specialClasses.get(name);
return defineClass(name, b, 0, b.length);
}
}
如果我想在 上执行转换(例如检测),我只需在调用它之前修改它即可。specialClasses
byte[]
defineClass()
我还想转换 System 类加载器提供的类,但 System 类加载器似乎没有提供任何访问它提供的类的原始值的方法,而是直接为我提供对象。byte[]
Class
我可以使用一个工具,所有加载到JVM中的类,但这会增加我不想分析的类的开销;我真的只想对 MyClassLoader 加载的类进行检测。-javaagent
- 有没有办法检索父类装入器提供的类的原始值,以便我可以在定义自己的副本之前检测它们?
byte[]
- 或者,有没有办法模拟System类加载器的功能,就它从哪里获取它而言,以便MyClassLoader可以检测和定义所有System类(Object,String等)的副本?
byte[]
编辑:
所以我尝试了另一种方法:
- 使用 ,捕获加载的每个类,并将其存储在哈希表中,并由类的名称进行键控。
-javaagent
byte[]
- MyClassLoader 不是将系统类委托给其父类装入器,而是使用类名从此哈希表中加载其字节码并定义它
从理论上讲,这将允许MyClassLoader使用检测定义自己的系统类版本。但是,它失败,并带有
java.lang.SecurityException: Prohibited package name: java.lang
显然,JVM 不喜欢我自己定义类,即使它(理论上)应该来自引导加载类的同一来源。寻找解决方案的工作仍在继续。java.lang
byte[]
编辑2:
我为这个问题找到了一个(非常粗略的)解决方案,但是如果一个比我更了解Java类加载/工具的复杂性的人可以想出一些不那么粗略的东西,那就太好了。