但是在流行的SO answer中我发现永久生成不是堆
的一部分我搞砸了这些矛盾的数据。我相信在这两个地方数据有效但有保留。请为我澄清这个问题。永久生成(非堆):包含所有内容的池 虚拟机本身的反射数据,如类和 方法对象。对于使用类数据共享的Java VM,这个 生成分为只读和读写区域。
我只谈谈Sun / Oracle jvms。
我已经阅读了jvm gcs(serial,parallel,cms和g1)的解释,我没有看到关于permgen的提及,它认为永久生成不是堆部分。
答案 0 :(得分:4)
我相信你引用了来自here的关于甲骨文官方网站的图表,是的,他们引用了“永久代”作为堆区域,但我想这只是试图解释JVM内存中的“世代” ;但据我所知(我猜很多专家会同意)“永久生成”不是堆区域的一部分,它是非堆区域的一部分,JVM用于内部目的,如JIT优化,方法领域等。
我想在下面引用3个官方Oracle参考资料,以帮助您确信“永久生成”不是堆区域的一部分。
在上面的第一个链接中,您可以清楚地看到Java解释了Java管理2种内存 - 堆和非堆内存,然后它们列出了每个内存中的“代”记忆的类型。您可以在“监视内存消耗”链接中阅读本节,下面是一些摘录。
然后在上面的第二个链接中,GC开发人员已经很好地解释了“永久代”的目的和洞察力,使用它可以清楚地理解“永久代”不是一堆区域,请参阅博客中的下图:
然后在上面的第三个链接中,您可以参考第3.2节“测量”中完成的内存测量,这也清楚地表明“永久生成”不是堆区域的一部分。 / p>
另外,你会知道在“Tenured generation”中完整的GC之后,在最坏的情况下,JVM会抛出内存异常但不会将对象提升为“永久生成”,因为它不是堆区域的一部分。 / p>
检查下图,可以找到许多这样的图解释JVM的内存调整参数。如果从内存调整JVM参数的角度看也是如此,那么“永久生成”不是堆区域的一部分也是不言而喻的。
现在,我认为你应该清楚,图(及其文章)只是为了从“世代”角度解释JVM内存概念,但在实现中JVM并不认为“永久代”是堆内存的一部分,它可以促进长寿命对象。
答案 1 :(得分:1)
Java 8没有PermGen,但是MetaSpace提供了相同的功能并且工作方式相似但不相同。
Java< = 7有一个PermGen,虽然它是一个Java托管空间,但它不是分配对象的堆。它不计入最大堆大小,也不计入32例如,CompressOops可以寻址的GB限制。它被清理为垃圾收集的一部分。
将它放在同一个图表中是有意义的,但它并不意味着PermGen / MetaSpace是同一堆的一部分。
另请注意,当堆空间用完时,您将获得
java.lang.OutOfMemoryError: Heap space space
然而,当你用完PermGen时,你会得到一个不同的错误。
java.lang.OutOfMemoryError: PermGen space
https://plumbr.eu/outofmemoryerror/java-heap-space
答案 2 :(得分:0)
Permgen是Java 7及更早版本中固定大小的内存区域。它已在Java 8中删除(release notes)。删除后我有以下原因:
自Java 8以来,发生在permgen中的内存对象被置于metaspace。元数据空间是可调整大小的内存区域并被放入堆中。