我目前正在用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”
它们之间的区别是什么?
我目前正在用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”
它们之间的区别是什么?
堆内存
堆内存是Java VM为所有类实例和数组分配内存的运行时数据区域。堆的大小可以是固定的,也可以是可变的。垃圾收集器是一种自动内存管理系统,用于回收对象的堆内存。
Eden Space:最初为大多数对象分配内存的池。 幸存者空间:包含在Eden空间的垃圾回收中幸存下来的对象的池。 Tenured Generation或Old Gen:包含幸存者空间中已存在一段时间的对象的池。
非堆内存
Non-heap memory includes a method area shared among all threads and memory required for the internal processing or optimization for the Java VM. It stores per-class structures such as a runtime constant pool, field and method data, and the code for methods and constructors. The method area is logically part of the heap but, depending on the implementation, a Java VM may not garbage collect or compact it. Like the heap memory, the method area may be of a fixed or variable size. The memory for the method area does not need to be contiguous.
永久生成:包含虚拟机本身的所有反射数据的池,例如类和方法对象。对于使用类数据共享的Java vm,这一代被划分为只读和读写区域。 代码缓存:HotSpot Java虚拟机还包括一个代码缓存,包含用于编译和存储本机代码的内存。
这里有一些关于如何使用Jconsole的文档。
在Java8中,非堆区域不再包含永久生成,而是包含元空间,这是Java8中的一个主要变化,应该消除java的内存不足错误,因为元空间大小可以根据jvm类数据所需的空间而增加。
new关键字在Java堆上分配内存。堆是内存的主池,整个应用程序都可以访问。如果没有足够的可用内存分配给该对象,JVM将尝试使用垃圾收集从堆中回收一些内存。如果它仍然无法获得足够的内存,则抛出OutOfMemoryError,并且JVM退出。
堆被分成几个不同的部分,称为代。随着对象在更多垃圾收集中存活下来,它们将被提升到不同的代。老一辈的人不经常被垃圾收集。因为这些对象已经被证明具有更长的生命周期,所以它们不太可能被垃圾收集。
第一次构建对象时,将它们分配到Eden Space中。如果他们在垃圾收集中幸存下来,他们就会被提升到幸存者空间,如果他们在那里活得足够长,他们就会被分配给终身代。这一代的垃圾收集频率要低得多。
There is also a fourth generation, called the Permanent Generation, or PermGen. The objects that reside here are not eligible to be garbage collected, and usually contain an immutable state necessary for the JVM to run, such as class definitions and the String constant pool. Note that the PermGen space is planned to be removed from Java 8, and will be replaced with a new space called Metaspace, which will be held in native memory. reference:http://www.programcreek.com/2013/04/jvm-run-time-data-areas/
Java堆内存是操作系统分配给JVM的内存的一部分。
对象驻留在一个称为堆的区域中。堆是在JVM启动时创建的,并且在应用程序运行时可以增加或减少堆的大小。当堆满时,将收集垃圾。
你可以在下面的SE问题中找到更多关于伊甸园空间,幸存者空间,终身空间和永久生成的细节:
年轻,终身和烫发一代
自Java 8发布以来,PermGen已被Metaspace取代。
关于您的疑问:
Eden Space, Survivor Space, Tenured Space是堆内存的一部分 元空间和代码缓存是非堆内存的一部分。
Codecache: Java虚拟机(JVM)生成本机代码并将其存储在称为Codecache的内存区域中。JVM出于各种原因生成本机代码,包括动态生成解释器循环、Java本机接口(JNI)存根,以及由即时(JIT)编译器编译成本机代码的Java方法。到目前为止,JIT是codecache的最大用户。
堆分为年轻代和老代如下:
年轻一代:指一个物体在短时间内生活过的地方,它被分为两个空间:
伊甸园空间:当对象创建时使用新的关键字内存分配在这个空间上。 幸存者空间(S0和S1):这是一个池,其中包含在Eden的小型java垃圾收集之后幸存下来的对象 空间。
Old Generation:这个池基本上包含永久和虚拟(保留)空间,并将保存那些在Young Generation的垃圾收集后幸存下来的对象。
Tenured Space:该内存池包含在多次垃圾回收后存活的对象 从幸存者空间收集垃圾后。
解释
让我们假设我们的应用程序刚刚启动。
所以此时这三个空间都是空的(Eden, S0, S1)
每当创建一个新对象时,它都被放置在伊甸园空间中。
当Eden空间满时,垃圾收集过程(minor GC)将在Eden空间上进行,所有幸存的对象都被移动到S0。
然后我们的应用程序继续运行,在Eden空间中创建新对象,下一次垃圾收集进程运行时,它会查看Eden空间和S0中的所有对象,任何幸存的对象都被移动到S1中。
PS:根据对象应该在Survivor空间中存活多长时间的配置,对象也可以来回移动到S0和S1,然后达到阈值的对象将移动到老一代堆空间。