如何在Java中加载修改过的超类? 我有甲级和乙级 我创建了一个CustomClassLoader扩展ClassLoader以使用定义类(className,byte[],offset,length) 我已经实例化了一个新的CustomClassLoader(Thread.currentThread().getContextClassLoader())。 因此,CustomClassLoader的父级是来自当前线程的ClassLoader 我已经使用ASM框架修改了B类。我已经在一个.class文件中编写了修改过的类,并使用了反编译器来确保它正常工作。它是有效的 我已将修改后的B类添加到CustomClassLoader中 我已经用CustomClassLoader设置了Thread.currentThread().setContextClassLoader() 我已经使用Class.forName(字符串,true,CustomClassLoader)加载了一个 但是加载的B类似乎是原始类
我做错了什么? 如果您需要更多信息,我的上有一个详细的主题。Java类加载器首先搜索父类加载器,然后再查找子类加载器 ClassLoader中的loadClass方法按顺序执行这些任务, 调用以加载类时:如何在Java中加载修改过的超类? 我有甲级和乙级 我创建了一个CustomClassLoader扩展ClassLoader以使用定义类(className,byte[],offset,length) 我已经实例化了一个新的CustomClassLoader(Thread.currentThread().getContextClassLoader())。 因此,CustomClassLoader的父级是来自当前线程的ClassLoader 我已经使用ASM框架修改了B类。我已经在一个.class文件中编写了修改过的类,并使用了反编译器来确保它正常工作。它是有效的 我已将修改后的B类添加到CustomClassLoader中 我已经用CustomClassLoader设置了Thread.currentThread().setContextClassLoader() 我已经使用Class.forName(字符串,true,CustomClassLoader)加载了一个 但是加载的B类似乎是原始类,java,classloader,superclass,java-bytecode-asm,Java,Classloader,Superclass,Java Bytecode Asm,我做错了什么? 如果您需要更多信息,我的上有一个详细的主题。Java类加载器首先搜索父类加载器,然后再查找子类加载器 ClassLoader中的loadClass方法按顺序执行这些任务, 调用以加载类时: 如果类已经加载,它将返回它 否则,它会将新类的搜索委托给父类加载器。 如果父类装入器未找到该类,loadClass将调用findClass方法查找并装入该类 (-Oracle) 如果要更改顺序,还需要重写loadClass方法,但是有许多警告,除非您非常了解类加载,否则不建议这样做 更简单的
loadClass
方法,但是有许多警告,除非您非常了解类加载,否则不建议这样做
- 更简单的选择是确保父类加载器无法找到原始类
B
- 对于大多数情况,处理线程的上下文类加载器是过时的,因为它没有影响。这更像是一个惯例;如果有其他代码查询和使用它,设置它会产生影响。对于标准类加载过程,它没有任何意义。不幸的是,文档中没有提到这一点,使它看起来像是一件相关的事情。也许,当它被添加时,它的目的是要有更多的意义
- 当通过自定义加载程序加载
时,它将委托给其父加载程序,返回父加载的类A
A
- 解析类引用时,JVM将始终使用引用方的定义加载程序。因此,当解析从
到A
的引用时,JVM将始终使用定义类B
A
- 有几件事需要知道:
A
,那么它也无法解决问题,因为它仍然返回父类的A
,父类的引用将使用父类解析。由于您在请求A
之前调用defineClass
,因此查找顺序根本不重要,因为您的自定义加载程序已经定义了B
,如果有人请求B
,它会返回该加载程序
因此,您可以让自定义加载程序也加载并定义
A
。或者在加载B
之前,在系统ClassLoader
上对defineClass
使用带有访问覆盖的反射。最干净的解决方案是将类修改逻辑实现为Java代理,它可以在加载时使用Instrumentation API截取并更改B
的定义。“a”类未加载,因此ClassLoader子类将类加载委托给ClassLoader父类。但是B加载在子级中(修改后的版本加载在子级中),所以当A因为A扩展了B而需要B时,为什么B从父级加载(加载原始版本)?“但是B加载在子级中”是什么意思?如果父类加载器中存在B,则它不会加载到子类中,因为每个不重写loadClass
的类加载器都会首先委托给其父类,并且只有在父类中找不到它时才会尝试将其加载到子类中。我必须在运行时更改B类字节码。因此,为了保存修改后的B类,我必须使用child.defineClass(),因为parent.defineClass()不可见,并且父类加载器中可能存在原始B类。-B被修改并加载到子级-A从子级加载->委托到父级-A扩展B-B似乎是从父级加载-B没有保存到父级,所以父级加载B使用URL我想-父级加载原始B类-B加载两次:在父级中原始,在子级中修改。我已经用它来解决我的问题。我希望这不是太脏:/