JVM如何处理动态类

时间:2015-01-22 20:28:31

标签: java jvm bytecode

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

  

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

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

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

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

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

2 个答案:

答案 0 :(得分:7)

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

  

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

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

  

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

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

  

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

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

  

JVM如何知道以不同于“普通”类的方式处理动态类?

有一个特殊的动态类示例。这些是在运行时生成的lambda类。使它们与众不同的是它们不受类加载器的约束,它们甚至没有正常的类名。当该类的所有实例都未使用时,它们将被卸载。

来自InnerClassLambdaMetafactory

UNSAFE.defineAnonymousClass(targetClass, classBytes, null);

该类没有附加类名(也不是ClassLoader)

答案 1 :(得分:2)

文件系统上的.class数据,jar文件内部或ASM等工具动态创建的数据没有区别。

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

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

正如我所说,它完全一样。 JVM并不知道其中的差异。

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

同样,JVM并不知道差异所以我猜。

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

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