类定义存储在方法区域中,如Java虚拟机规范所述(The Java® Virtual Machine Specification Java SE 7 Edition):
方法区域是在虚拟机启动时创建的。虽然 方法区域在逻辑上是堆的一部分,简单的实现可能 选择 不要垃圾收集或压缩 。
正如我们所知,一些字节码工具,如 ASM , cglib , javassist ,Hibernate和Spring框架正在使用它们。对于公共类文件,JVM加载并解析和初始化并最终使用它,我对JVM如何动态处理字节码工具生成的类感到困惑。我的问题是:
如果JVM加载,则将动态类解析并初始化为公共类文件?
它们也存储在方法区域中吗?
JVM如何卸载和清理动态类定义以防止自身发生OutOfMemoryError?
答案 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
与非动态类相同。通过卸货虽然我不知道这种情况发生的频率