Perm space和Heap space的区别

79

首先,Perm空间和Heap空间有什么区别(JVM如何选择使用每个内存空间)?

其次,更重要的是,对于标准MVC类型的Java应用程序,推荐使用什么样的比例?

3个回答

81
存储了Java程序创建的所有对象。垃圾回收器监视堆的内容,当您停止使用对象(即没有对该对象的引用)时,从堆中释放内存。
相比之下, 存储原始数据类型(如int和char),通常是本地变量和函数返回值。它们不会被垃圾回收。 永久代 指堆的一个特殊部分。请参阅此SO答案以了解详细解释:什么是永久代?

1
你提供的链接中写道“堆的一部分” - 所以它真的是“栈的特殊部分”吗? 它更有意义成为堆的一部分(甚至是某种静态数据段),而不是栈,因为栈并不适合这种类型的事情。 - Sergei Tachenov
1
这是堆的一个特殊部分。在你评论之前,我已经编辑了我的答案,但我仍然感谢你的纠正。 :) - Olhovsky
1
对于第二个问题有什么推荐吗? - Gareth
2
@Gareth:这不是什么需要担心的事情。有些JVM甚至没有为永久区分配专门的存储空间。如果你遇到java.lang.OutOfMemory异常,那么可以使用这个工具来可视化永久区的使用量:http://www.alphaworks.ibm.com/tech/pmat,然后如果你的永久区用完了(在我的经验中很少出现),你可以通过命令行选项-XX:MaxPermSize=256m来增加永久区大小,将永久区大小设置为256MB。 - Olhovsky
1
好的,我明白了。所以实际上没有任何百分比规则之类的东西。谢谢。 - Gareth

35

就我个人而言,我不认为PermGen是堆的特殊部分。

我更愿意将堆视为专用于存储对象实例的内存区域,而将PermGen视为专用于存储类定义的区域。因此,堆的生命周期与应用程序相关联,而PermGen的生命周期则与JVM相关联。

一个很好的例子说明了应用程序及其JVM可以具有不同的生命周期,在Java EE容器中。在应用程序服务器中,应用程序可以在不重新启动服务器的情况下部署和取消部署。在取消部署(或重新部署)期间,释放所有对象实例(即堆空间)很容易,但是清除由该应用程序加载的所有类以释放PermGen则相对棘手,因为JVM仍可能引用其中一些类。

这种情况之一是泄漏的驱动程序。在部署应用程序时,将加载JDBC驱动程序并使用DriverManager进行注册。当卸载该应用程序时,DriverManager仍然存在,并保留对驱动程序、其原始类加载器以及该类加载器加载的所有内容的引用。因此,会在PermGen中创建内存泄漏,但这并不是应用程序中内存管理的错误。

的确,像JRocket这样的JVM根本没有PermGen,一切都存储在堆中。只有在这种情况下,您才可以将PermGen称为堆的“特殊部分”。即使在这种情况下,我们仍应将PermGen和堆视为不同的内容,因为它们具有非常不同的目的和非常不同类型的内存泄漏。

更新:在Oracle的JDK 8中,PermGen被替换为“Metaspace”,现在正式成为堆的一部分。我们不再需要专门调整PermGen。


0

在堆中分配的内存不能被命名。

这意味着 int x(它的名称)是在堆栈中分配的。您可以通过其名称访问指针,因此指针位于堆栈中。您无法通过名称访问对象,因为它没有名称。必须通过指针访问(无名)对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接