如何在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中加载修改过的超类? 我有甲级和乙级 我创建了一个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方法,但是有许多警告,除非您非常了解类加载,否则不建议这样做 更简单的

我做错了什么? 如果您需要更多信息,我的上有一个详细的主题。

Java类加载器首先搜索父类加载器,然后再查找子类加载器

ClassLoader中的loadClass方法按顺序执行这些任务, 调用以加载类时:

  • 如果类已经加载,它将返回它
  • 否则,它会将新类的搜索委托给父类加载器。
  • 如果父类装入器未找到该类,loadClass将调用findClass方法查找并装入该类
  • (-Oracle)

    如果要更改顺序,还需要重写
    loadClass
    方法,但是有许多警告,除非您非常了解类加载,否则不建议这样做

    • 更简单的选择是确保父类加载器无法找到原始类
      B

      • 有几件事需要知道:

        • 对于大多数情况,处理线程的上下文类加载器是过时的,因为它没有影响。这更像是一个惯例;如果有其他代码查询和使用它,设置它会产生影响。对于标准类加载过程,它没有任何意义。不幸的是,文档中没有提到这一点,使它看起来像是一件相关的事情。也许,当它被添加时,它的目的是要有更多的意义
        • 当通过自定义加载程序加载
          A
          时,它将委托给其父加载程序,返回父加载的类
          A
        • 解析类引用时,JVM将始终使用引用方的定义加载程序。因此,当解析从
          A
          B
          的引用时,JVM将始终使用定义类
          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加载两次:在父级中原始,在子级中修改。我已经用它来解决我的问题。我希望这不是太脏:/