java内存池是如何划分的?

我目前正在用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”

它们之间的区别是什么?

214810 次浏览

堆内存

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

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

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

  • Tenured GenerationOld Gen:幸存者空间中已存在一段时间的对象池。

非堆内存

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

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

  • Code Cache: HotSpot Java虚拟机还包含代码缓存,包含用于编译和存储本机代码的内存。

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

在Java8中,非堆区域不再包含永久生成,而是包含元空间,这是Java8中的一个主要变化,应该消除java的内存不足错误,因为元空间大小可以根据jvm类数据所需的空间而增加。

new关键字在Java堆上分配内存。堆是内存的主池,整个应用程序都可以访问。如果没有足够的可用内存分配给该对象,JVM将尝试使用垃圾收集从堆中回收一些内存。如果它仍然无法获得足够的内存,则抛出OutOfMemoryError,并退出JVM。

堆被分成几个不同的部分,称为代。随着对象在更多垃圾收集中存活下来,它们将被提升到不同的代。老一辈的人不经常被垃圾收集。因为这些对象已经被证明具有更长的生命周期,所以它们不太可能被垃圾收集。

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

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

几个线程的Java内存图  Java内存分布图 < / p >

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

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

enter image description here

你可以在下面的SE问题中找到关于伊甸园空间,幸存者空间,终身空间和永久世代的更多细节:

Young, Tenured and Perm generation .

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

关于您的疑问:

  1. Eden Space, Survivor Space, Tenured Space是堆内存的一部分
  2. 元空间和代码缓存是非堆内存的一部分。

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

堆分为年轻代和老代如下:

年轻一代:它是一个物体在短时间内生活的地方,它被分为两个空间:

  • 伊甸园空间:当对象创建时使用new关键字内存分配在这个空间上。
  • 幸存者空间(S0和S1):这是一个池,它包含了在Eden的小型java垃圾收集后幸存下来的对象 李空间。< / >

旧一代:这个池基本上包含了永久和虚拟(保留)空间,并将保存那些在Young Generation垃圾收集后幸存下来的对象。

  • 年老代空间:此内存池包含在多次垃圾回收后存活的对象
  • . .

enter image description here

解释

让我们假设我们的应用程序刚刚启动。

所以此时这三个空间都是空的(Eden, S0, S1)

每当创建一个新对象时,它都被放置在伊甸园空间中。

当Eden空间满时,垃圾收集过程(minor GC)将在Eden空间上进行,所有幸存的对象都被移动到S0。

然后我们的应用程序继续运行,在Eden空间中创建新对象,下一次垃圾收集进程运行时,它会查看Eden空间和S0中的所有对象,任何幸存的对象都被移动到S1中。

PS:根据对象应该在Survivor空间中存活多长时间的配置,对象也可以来回移动到S0和S1,然后达到阈值的对象将移动到老一代堆空间。