java内存池如何划分?


224

我目前正在使用jconsole监视Java应用程序。内存选项卡使您可以选择:

Heap Memory Usage
Non-Heap Memory Usage
Memory Pool “Eden Space”
Memory Pool “Survivor Space”
Memory Pool “Tenured Gen”
Memory Pool “Code Cache”
Memory Pool “Perm Gen”

它们之间有什么区别?


假设您使用的是Sun JDK,则最佳解决方案将在其文档中找到:调整垃圾回收(JDK 1.5)垃圾回收常见问题解答(JDK 1.4)
kdgregory 2009年

Answers:


327

堆内存

堆内存是Java VM从中为所有类实例和数组分配内存的运行时数据区。堆的大小可以固定或可变。垃圾收集器是一个自动内存管理系统,可以回收对象的堆内存。

  • Eden Space:最初为大多数对象分配内存的池。

  • 幸存者空间:包含在Eden空间的垃圾回收中幸存的对象的池。

  • 终身生成生成:包含幸存者空间中已存在一段时间的对象的池。

非堆内存

非堆内存包括在所有线程之间共享的方法区域以及Java VM的内部处理或优化所需的内存。它存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码。方法区域在逻辑上是堆的一部分,但是根据实现的不同,Java VM可能不会对其进行垃圾回收或压缩。像堆内存一样,方法区域的大小可以固定或可变。方法区域的内存不必是连续的。

  • 永久生成:包含虚拟机本身所有反射数据的池,例如类和方法对象。对于使用类数据共享的Java VM,这一代被分为只读和读写区域。

  • 代码缓存:HotSpot Java VM还包括代码缓存,其中包含用于编译和存储本机代码的内存。

这是一些有关如何使用Jconsole的文档


4
我不确定@dfa是否完全正确,因为Java虚拟机规范明确指出:“尽管方法区域在逻辑上是堆的一部分,但简单的实现可能选择不进行垃圾收集或压缩。” 但是,很明显,jconsole将代码缓存和永久生成显示为非堆,这似乎与规范相矛盾。谁能对此矛盾提供更多的澄清?
James Bloom 2013年

@JamesBloom-我也在想同样的事情。即使基本定义声明了哪个内存池属于哪种类型(堆/非堆),它也可能会改变,状态是明确的吗?
Umang Desai

2
该文档的别名为:docs.intergral.com/pages/viewpage.action?pageId=22478944该文档包含有关JVM的其他一些不错的信息,值得浏览
Steve Siebert 2014年

1
尽管有很多支持,实际上答案并不是那么有意义。例如,“在伊甸园空间垃圾回收中幸存的对象”是什么意思?这些物体在幸存之后是从伊甸园移到幸存者空间,还是在伊甸园中被视为幸存者空间?那么,除了Eden空间之外的池中的垃圾收集又会如何呢?完全不清楚。
Mikhail Batcer '16

并且不要忘记堆栈(在非堆侧):)
Toothless Seer

70

new关键字在Java堆上分配内存。堆是主要的内存池,可供整个应用程序访问。如果没有足够的内存可用于分配给该对象,则JVM会尝试通过垃圾回收从堆中回收一些内存。如果仍然无法获得足够的内存,则会引发OutOfMemoryError并退出JVM。

堆分为几个不同的部分,称为几代。随着对象在更多垃圾收集中幸存下来,它们被提升为不同的世代。老一辈人不经常收集垃圾。由于已经证明这些对象的寿命更长,因此它们不太可能被垃圾回收。

首次构造对象时,它们会在Eden空间中分配。如果他们在垃圾收集中幸存下来,则将被提升到幸存者空间,如果他们在那里生存足够长的时间,则会被分配给终身代。这一代的垃圾收集频率要低得多。

还有第四代,称为永久代或PermGen。驻留在此处的对象不适合进行垃圾回收,并且通常包含JVM运行所必需的不可变状态,例如类定义和String常量池。请注意,PermGen空间计划从Java 8中删除,并将由名为Metaspace的新空间替换,该空间将保存在本机内存中。参考:http : //www.programcreek.com/2013/04/jvm-run-time-data-areas/

在此处输入图片说明 在此处输入图片说明


该图看起来很容易解释...对任何GC算法都有效吗?G1有不同的设置。
Venkateswara Rao

@Pythoner我认为应该用深紫色标记,-XX:PermSize而不是-XX:MaxPermSize上面已经定义的标记。
阿努拉格


23

Java堆内存是操作系统分配给JVM的内存的一部分。

对象驻留在称为堆的区域中。JVM启动时会创建堆,并且在运行应用程序时可能会增加或减小堆的大小。当堆变满时,将收集垃圾。

在此处输入图片说明

您可以在以下SE问题中找到有关伊甸园空间,幸存者空间,终身空间和永久生成的更多详细信息:

年轻,终身制和烫发一代

自Java 8发布以来,PermGen已被Metaspace取代。

关于您的查询:

  1. 伊甸园空间,幸存者空间,保有权空间是堆内存的一部分
  2. 元空间和代码缓存是非堆内存的一部分。

代码缓存: Java虚拟机(JVM)生成本机代码并将其存储在称为代码缓存的内存区域中。JVM出于各种原因生成本机代码,其中包括动态生成的解释器循环,Java本机接口(JNI)存根,以及由即时(JIT)编译器编译为本机代码的Java方法。到目前为止,JIT是代码缓存的最大用户。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.