JVM如何处理动态类

How does JVM deal with dynamic classes

Class 定义存储在方法区中,正如 Java 虚拟机规范所说 (The Java® Virtual Machine Specification Java SE 7 Edition):

The method area is created on virtual machine start-up. Although the method area is logically part of the heap, simple implementations may choose not to either garbage collect or compact it.

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

  1. 如果 JVM 加载、解析和初始化动态 classes 作为普通 class 文件?

  2. 它们也存储在方法区中吗?

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

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

If JVM loads, parses and initializes the dynamic classes as the common class file?

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

Are they stored in the Method Area as well?

它们的存储方式相同,实际上很难判断 class 是否是动态的。

How does JVM unload and clean the dynamic class definitions to prevent itself from occurring an OutOfMemoryError?

当卸载它们所在的 ClassLoader 时,JVM 可以卸载 classes。无论 classes 是否动态,都是如此。

how could the JVM know to treat dynamic classes any differently than 'normal' classes?

有一个动态 classes 的例子是特殊的。这些是在运行时生成的 lambda classes。它们的不同之处在于它们没有绑定到 class 加载器,它们甚至没有一个正常的 class 名称。当 class 的所有实例都未使用时,它们将被卸载。

来自InnerClassLambdaMetafactory

UNSAFE.defineAnonymousClass(targetClass, classBytes, null);

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

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

事实上,当 class 加载程序加载 class 时,只是 byte[] 如何用 .class 数据填充字节数组取决于 class 加载器从文件系统、jar 或 zip 文件中、从 URL、动态生成等中获取它

如果 JVM 加载、解析和初始化动态 classes 作为普通 class 文件?

正如我所说,完全一样。 JVM 不知道区别。

它们也存储在方法区中吗?

同样,JVM 不知道其中的区别,所以我猜。

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

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