Java JVM如何处理动态类

Java JVM如何处理动态类,java,jvm,bytecode,Java,Jvm,Bytecode,类定义存储在方法区域中,正如Java虚拟机规范所说(): 方法区域是在虚拟机启动时创建的。虽然 方法区域在逻辑上是堆的一部分,简单的实现可以 选择不进行垃圾收集或压缩 正如我们所知,一些字节码工具,如ASM、cglib、javassist、Hibernate和Spring框架正在使用它们。对于一个普通的类文件,JVM加载、解析、初始化并最终使用它,我对JVM如何动态处理字节码工具生成的类感到困惑。我的问题是: 如果JVM将动态类加载、解析并初始化为公共类文件 它们是否也存储在方法区域 JVM如何

类定义存储在方法区域中,正如Java虚拟机规范所说():

方法区域是在虚拟机启动时创建的。虽然 方法区域在逻辑上是堆的一部分,简单的实现可以 选择不进行垃圾收集或压缩

正如我们所知,一些字节码工具,如ASM
cglibjavassist、Hibernate和Spring框架正在使用它们。对于一个普通的类文件,JVM加载、解析、初始化并最终使用它,我对JVM如何动态处理字节码工具生成的类感到困惑。我的问题是:

  • 如果JVM将动态类加载、解析并初始化为公共类文件

  • 它们是否也存储在方法区域

  • JVM如何卸载和清理动态类定义以防止自身发生OutOfMemoryError


  • 所有类都在运行时加载,可能编译为本机代码。因此,在程序启动后生成的类没有什么特殊之处

    如果JVM将动态类加载、解析并初始化为公共类文件

    它以与程序启动时存在的类相同的方式加载

    它们是否也存储在方法区域

    它们以相同的方式存储,事实上很难判断类是否是动态的

    JVM如何卸载和清理动态类定义以防止自身发生OutOfMemoryError

    JVM可以在类装入器中的类被卸载时卸载这些类。无论类是否是动态的,这都是正确的


    JVM怎么知道对待动态类与对待“普通”类有什么不同

    这里有一个特殊的动态类示例。这些是在运行时生成的lambda类。它们的不同之处在于它们没有绑定到类装入器,甚至没有一个普通的类名。当该类的所有实例都未使用时,它们将被卸载

    InnerClassLambdaMetafactory

    UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
    

    类没有附加类名(也没有类加载器)

    文件系统中、jar文件中或由ASM等工具动态创建的
    .class
    数据之间没有区别

    事实上,当类加载器加载类时,它只是一个
    byte[]
    如何用
    填充字节数组。类
    数据由类加载器从文件系统、jar或zip文件、URL、动态生成的等处获取

    如果JVM将动态类加载、解析并初始化为公共类文件?

    正如我所说,这是完全一样的。JVM不知道其中的区别

    它们是否也存储在方法区域中?

    再说一次,JVM不知道区别,所以我猜

    JVM如何卸载和清理动态类定义以防止自身发生OutOfMemoryError


    与非动态类的方式相同。通过卸载,虽然我不知道这种情况发生的频率

    JVM怎么知道对待动态类与对待“正常”类有什么不同?@down voter,你能给我一个关于Q3的答案吗?@NathanHughes Lambdas是这些类被不同对待的一个例子(见我的答案)。顺便说一句,我没有否决这个,我投了更高的票。我特别欣赏关于lambdas的部分,“在Java8中,元空间不会产生OutOfMemoryError”,不是吗?什么是
    java.lang.OutOfMemoryError:Metadata space
    那么?@eis是真的,meta space的最大大小要大得多,但是你仍然可以得到OOME,这只是不太可能。实际上,即使是“匿名”类也有一个名称,因为它是类文件格式的一部分。您将在调试时看到它。使它们特别的是,名称不需要是唯一的,并且不能通过它们的名称访问这些类(因为它们没有记录在类加载器中)。顺便说一句,
    MethodHandle
    s也在内部使用此功能(这就是为什么它也存在于Oracle的Java 7实现中)。感谢您的回答,事实上,我对第三季度感到困惑