Java堆术语:年轻一代,老一代和永久一代?


318

我试图了解Java堆术语中的年轻老年永久一代的概念,更具体地说是三代之间的交互。

我的问题是:

  • 什么是年轻一代?
  • 什么是老一辈?
  • 什么是永久一代?
  • 这三代人之间是如何相互作用/相互联系的?

假设您正在谈论Sun JDK / OpenJDK,请参阅OpenJDK网站上Storage Management上的页面。底部有几个指向更多信息的链接。
尼古拉斯·赖利

1
也与此问题“终身代”有关
gstackoverflow 2014年

Answers:


304

这似乎是一种常见的误解。在Oracle的JVM中,永久生成不是堆的一部分。它是用于类定义和相关数据的单独空间。在Java 6及更早版本中,实习生字符串也存储在永久代中。在Java 7中,插入的字符串存储在主对象堆中。

这是永久世代的好帖子。

我喜欢Oracle 关于JConsole指南中对每个空间的描述:

对于HotSpot Java VM,用于串行垃圾回收的内存池如下。

  • Eden Space(堆):最初为大多数对象分配内存的池。
  • 生存空间(堆):包含在Eden空间的垃圾收集中幸存的对象的池。
  • 永久生成(堆):包含幸存者空间中已存在一段时间的对象的池。
  • 永久生成(非堆):该池包含虚拟机本身的所有反射数据,例如类和方法对象。对于使用类数据共享的Java VM,这一代被分为只读和读写区域。
  • 代码缓存(非堆):HotSpot Java VM还包括代码缓存,其中包含用于编译和存储本机代码的内存。

Java使用分代垃圾回收。这意味着,如果您有一个对象foo(它是某个类的实例),则该对象幸存的垃圾回收事件越多(如果仍然有对其的引用),则它的推广就越多。它始于年轻一代(本身被划分为多个空间-伊甸园和幸存者),如果生存了足够长的时间,最终将进入终身一代。


2
我相信,从Java 7开始,字符串已不再永久存在。
蒂姆·古德曼

您是对的,我很惊讶这个问题幸存了这么久才被提及。然后,在Java 8中,永久生成将由元空间代替(尽管我不确定这将有何不同,除了默认情况下不受限制)
Joshua McKinnon

9
约书亚(Joshua)–“旧”是“ tenured”的代名词,“新”是“幸存者”的代名词吗?
joadha 2014年

1
烫发根是对Java 8只现有适用
lwpro2

2
如果您仍在等待答案,可以,您是正确的@joadha。看看这个链接:codeahoy.com/2017/08/06/basics-of-java-garbage-collection
recepinanc

197

堆分为以下几代:

青年一代:是短暂居住的地方,分为两个空间:

  • Eden Space:使用在此空间上分配的新关键字内存创建对象时。
  • Survivor Space:这是一个池,其中包含在从Eden空间进行Java垃圾回收之后仍然存在的对象。

老一代:该池基本上包含使用权和虚拟(保留)空间,并将容纳从Young Generation回收垃圾后幸存的那些对象。

  • 永久性空间:此内存池包含在多次垃圾回收之后仍然存在的对象,这意味着从幸存者空间进行垃圾回收之后仍然存在的对象。

永久生成:此存储池的名称也包含永久类的元数据和描述符信息,因此PermGen空间始终为类以及与类相关的那些(例如静态成员)保留。

Java8更新: PermGen被非常相似的Metaspace取代。
主要区别在于Metaspace可动态调整大小,即可以在运行时扩展。
Java Metaspace空间:无界(默认)

代码缓存(虚拟或保留):如果您使用的是HotSpot Java VM,则此代码缓存区域将包含用于存储本机代码的内存的代码缓存区域。

在此处输入图片说明

礼貌


@Premraj是什么意思,元空间会动态调整大小,即它可以在运行时扩展。?默认情况下它没有边框的唯一区别是?
gstackoverflow

1
很好..我可以知道方法区域,nativestack和运行时常量池在此图中位于何处吗?并据此持有什么?

如果将代码缓存用于本机方法代码,本机方法堆栈(每个线程将具有一个)将具有什么?

49

什么是年轻一代?

年轻一代是所有新对象分配和老化。当年轻一代填满时,这将导致少量垃圾收集。充满死亡物体的年轻一代可以很快收集到。一些幸存的物体会老化,并最终移交给老一代。

什么是老一辈?

老一代用来存放长幸存的对象。通常,为年轻一代对象设置一个阈值,并且当达到该年龄时,该对象将移至老一代。最终需要收集旧的一代。此事件称为大型垃圾收集

什么是永久一代?

永久代包含元数据需要由JVM来描述应用程序使用的类和方法。永久生成由JVM在运行时根据应用程序使用的类填充。

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

现在将忽略PermSize和MaxPermSize参数

这三代人之间是如何相互作用/相互联系的?

在此处输入图片说明

图像源和Oracle TechNetwork教程文章:http : //www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

上一篇文章中的“ 常规垃圾收集过程 ”通过许多图表说明了它们之间的交互。

看一下汇总图:

在此处输入图片说明


很好..我可以知道方法区域,nativestack和运行时常量池在此图中位于何处吗?并据此持有什么?

有关更多详细信息,请参考docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html。方法区域是在虚拟机启动时创建的。尽管方法区域在逻辑上是堆的一部分,但简单的实现可以选择不进行垃圾回收或压缩。每次运行时间常量池是从Java虚拟机的方法面积分配
拉温德拉巴布

您确定...我一直在阅读它的permgen空间(不是堆)的一部分吗?journaldev.com/2856/...

Oracle文档更加真实
Ravindra babu

是否以时间单位(例如ms)为年轻一代对象设置了阈值?还是GC回合?
非常客观的

16

Java虚拟机分为三代:年轻一代,老一代和永久一代。大多数对象最初是在年轻一代中分配的。老一代包含的对象在一些年轻一代集合中幸存了下来,还有一些大型对象可以直接在老一代中分配。永久生成包含JVM认为便于垃圾回收器管理的对象,例如描述类和方法的对象,以及类和方法本身。


1

SunHotSpot JVM中的内存分为三代:年轻一代,老一代和永久一代。

  • 年轻一代:将新创建的对象分配给年轻一代。
  • 上一代:如果新对象要求更大的堆空间,则会将其直接分配到上一代。幸存了几个GC周期的对象也被提升为旧一代,即在旧一代中居住的寿命长的对象。
  • 永久代:永久代保存JVM发现便于垃圾回收器管理的对象,例如描述类和方法的对象,以及类和方法本身。

仅供参考:永久gen不被视为Java堆的一部分。

这三代人之间是如何相互作用/相互联系的? 对象(大对象除外)首先分配给年轻一代。如果一个对象在x no之后仍然存在。垃圾收集周期的提升,它被提升为旧的/终身使用的一代。因此,可以说年轻一代包含寿命短的对象,而老一代包含寿命长的对象。永久一代不与其他两代交互。

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.