如image所示,Permgen被进一步分为几个部分。
如image所示,Permgen被进一步分为几个部分。
Any code is stored in this space(seems vague to me)?
所有已被解析的类的字节码都存储在permgen中。仅仅因为一个库有1.2MB的类,并不意味着JVM会从JAR中加载它们。很可能只有其中一小部分类被特定应用程序使用。
你可以运行许多大型应用服务器,其总JAR大小超过1GB,仅使用64MB permgen,因为只有其中一小部分类被使用。
还有这个例子:
class A {
// ... code
}
class B {
void method1() {
// something
}
void method2() {
A a = new A();
}
}
尽管这些类可能存在于同一个JAR文件中,但仅仅创建B的实例并不会导致A类被加载。如果您从未调用method2()
,那么JVM将永远不会加载A类。此外,与普遍的观点相反,permgen是可以进行垃圾回收的,如果空间变得很低,并且堆上没有引用到class A
的实例,那么A类就可以从permgen中删除。
关于PermGen问题的有趣文章:Java 8是否解决PermGen OutOfMemoryError问题?:
Oracle的JVM开发人员Jon Masamitsu在他的博客中曾在2006年解释过永久代的目的:永久代包含类的信息,例如字节码、名称和JIT信息。它存储在单独的空间中,因为它大多是静态的,并且通过分离可以更加优化垃圾回收。
实际上,PermGen 存储了所有静态代码。我认为这让你明白为什么 PermGen 中有一个代码区。
我将根据Jon Masamitsu的文章,引用以下内容,猜测上面的图表是一种错误的陈述(或者重新表述为:一种误导性的陈述):
因此,Java类存储在永久代中。这意味着什么?除了Java类的基本字段之外,还有:
类的方法(包括字节码)
类的名称(以指向字符串的对象形式也存储在永久代中)
常量池信息(从类文件中读取的数据,请参见JVM规范第4章获取所有详细信息)
与类相关联的对象数组和类型数组(例如,包含对方法引用的对象数组)。
JVM创建的内部对象(例如java/lang/Object或java/lang/exception)
编译器(JIT)用于优化的信息