网站首页 > java教程 正文
前文《Java面试必考问题:JVM内存区域如何划分? 》中介绍了Java虚拟机运行时内存是如何划分的。其中堆内存是虚拟机管理的最大的一块内存,也是垃圾回收最频繁的区域,程序中所有的对象实例都存放在堆内存中。本文主要介绍一下堆内存的主要构成。
根据对象存活的周期不同,把堆内存划分为几块,一般分为年轻代(Young)、老年代(Old)和永久代(Perm),其中只有HotSpot虚拟机才有永久代,在JDK1.8之后也取消了。这就是JVM的内存分代策略。
永久代是HotSpot虚拟机特有的概念,其他的虚拟机实现没有这一概念。HotSpot在JDK1.8之后就没有了永久代了,已经被元空间(Metaspace)替代。HotSpot在JDK1.7之前采用永久代来实现方法区,主要存放常量、类信息、静态变量等数据,这些方法区里的数据当时是存放在堆内存的永久代中。
给堆内存分代是为了提高对象内存分配和垃圾回收的效率,这样每次进行垃圾回收的时候就不需要遍历所有对象。接下来我们逐个介绍堆内存的各个区域。
年轻代(Young Generation)
年轻代也称为新生代,新生成的对象放在年轻代中的Eden区,大对象则直接放在老年代里。Eden的中文意思是伊甸园,这是圣经中记载人类始祖最早居住的地方。以Eden命名的意思就是表示这个区域用于存放新生的Java对象。
除了Eden区以外,年轻代还有另外一块区域叫Survivor区,也叫做幸存者空间。这个区域和Eden区在垃圾回收时配合使用。
Java语言有内置的垃圾回收(GC)机制,对于程序中不再使用的对象,由虚拟机来回收内存。Eden区对象的生存周期都很短,存活率很低,只有少部分能成为幸存者。因此,Eden区所需的空间更大,Eden区和Survivor区的默认比例是4:1。
从年轻代中回收内存被称为Minor GC。当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。一次Minor GC通常可以回收70% ~ 95% 的空间,回收效率很高。
Minor GC的过程
Survivor区分为两等份,一块是作为From Survivor区,另一块是作为To Survivor区。这两块内存是在GC过程中腾挪空间用的。
- GC开始前,对象只存在于Eden区和From Survivor区(S0区)中,To Survivor区(S1区)是空的。
- GC进行时,Eden区中所有存活的对象都会被复制到S1区,在S0区中仍存活的对象会根据它们的年龄值决定去向,年龄值达到一定的阀值的对象会被移到老年代中,其他没有达到阀值的对象会被复制到S1区。
- 接下来清空Eden区和S0区,新生代中存活的对象都在S1区了。
- 然后,S0区和S1区会交换角色,S0成为To Survivor区,S1成为From Survivor区。
虚拟机一直循环往复上述过程,每次GC完成,都会保证To Survivor区是空的。
当To Survivor区没有足够的空间存放上一次GC存活下来的对象时,需要将这些对象存放在老年代中。
老年代(Old Generationn)
在年轻代中经历了多次Minor GC后仍然顽强存活下来的对象,会进入老年代中。年轻代中的对象每熬过一轮垃圾回收,年龄值会加1,默认达到15岁,就能进入老年代了。
老年代中的对象生命周期较长,存活率比较高,在老年代中进行GC的频率相对而言较低,而且回收的速度也比较慢。
对老年代内存进行的GC操作称为Major GC。如果对整个堆(包括年轻代和老年代)进行GC操作,则称为Full GC。如果创建了一个大对象,Eden区放不下就要放到老年代,如果老年代也放不下,就会触发Full GC。另外如果显示运行 System.gc(), 也会触发Full GC。
内存分代的好处?
新创建的对象会在新生代中分配内存,经过多次回收仍然存活下来的对象存放在老年代。
新生代中的对象存活时间短,只需要在新生代区域中频繁进行GC,老年代中对象生命周期长,内存回收的频率相对较低,不需要频繁进行回收。
根据不同年代的特点采用合适的垃圾收集算法,提升了内存收集效率,这是内存分代带来的好处。
我会持续更新关于物联网、云原生以及数字科技方面的文章,用简单的语言描述复杂的技术,也会偶尔发表一下对IT产业的看法,欢迎大家关注,谢谢。
猜你喜欢
- 2025-08-05 前端小白都能看懂的8本书,第1本带你搞懂谷歌最新开源前端框架
- 2025-08-05 编程语言之萌化篇(二)
- 2025-08-05 IT人才才懂的段子2,谁说网友们看不懂的?程序员:哈哈哈哈
- 2025-08-05 如果可以从历史上抹去一种编程语言,你会选择哪个?
- 2025-08-05 漫谈:Java GC的那些事(一)
- 2025-08-05 计科专业的大一新生,如何提高编程能力?秃头哥简单说两句
- 2025-08-05 醒醒!程序员已沦为流水线螺丝钉,这就是血淋淋的真相
- 2025-08-05 19本高并发编程书籍推荐
你 发表评论:
欢迎- 08-05深入理解 Spring 设计模式:从实现原理到思想精髓
- 08-05工作中最常用的 8 种设计模式
- 08-05一文读懂设计模式,看这篇就够了
- 08-05java设计模式之责任链模式
- 08-05从复杂到优雅:用建造者和责任链重塑代码架构
- 08-05带你读Effective系列:创建对象-Builder构建器
- 08-05面试官:JDK中都用了哪些设计模式?
- 08-05工厂、建造者、装饰器、适配器:解密JDK设计模式的实战妙用
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)