Java虚拟机:JVM内存分代策略

Java虚拟机根据对象存活的周期不同,把堆内存划分为几块,一般分为新生代、老年代和永久代(对HotSpot虚拟机而言),这就是JVM的内存分代策略。

为什么要分代?

堆内存是虚拟机管理的内存中最大的一块,也是垃圾回收最频繁的一块区域,我们程序所有的对象实例都存放在堆内存中。给堆内存分代是为了提高对象内存分配和垃圾回收的效率。试想一下,如果堆内存没有区域划分,所有的新创建的对象和生命周期很长的对象放在一起,随着程序的执行,堆内存需要频繁进行垃圾收集,而每次回收都要遍历所有的对象,遍历这些对象所花费的时间代价是巨大的,会严重影响我们的GC效率,这简直太可怕了。

有了内存分代,情况就不同了,新创建的对象会在新生代中分配内存,经过多次回收仍然存活下来的对象存放在老年代中,静态属性、类信息等存放在永久代中,新生代中的对象存活时间短,只需要在新生代区域中频繁进行GC,老年代中对象生命周期长,内存回收的频率相对较低,不需要频繁进行回收,永久代中回收效果太差,一般不进行垃圾回收,还可以根据不同年代的特点采用合适的垃圾收集算法。分代收集大大提升了收集效率,这些都是内存分代带来的好处。

内存分代划分

Java虚拟机将堆内存划分为新生代老年代永久代,永久代是HotSpot虚拟机特有的概念,它采用永久代的方式来实现方法区,其他的虚拟机实现没有这一概念,而且HotSpot也有取消永久代的趋势,在JDK 1.7中HotSpot已经开始了“去永久化”,把原本放在永久代的字符串常量池移出。永久代主要存放常量、类信息、静态变量等数据,与垃圾回收关系不大,新生代和老年代是垃圾回收的主要区域。内存分代示意图如下:

 新生代(Young)

新生成的对象优先存放在新生代中,新生代对象朝生夕死,存活率很低,在新生代中,常规应用进行一次垃圾收集一般可以回收70% ~ 95% 的空间,回收效率很高。

HotSpot将新生代划分为三块,一块较大的Eden空间和两块较小的Survivor空间,默认比例为8:1:1。划分的目的是因为HotSpot采用复制算法来回收新生代,设置这个比例是为了充分利用内存空间,减少浪费。新生成的对象在Eden区分配(大对象除外,大对象直接进入老年代),当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。

GC开始时,对象只会存在于Eden区和From Survivor区,To Survivor区是空的(作为保留区域)。GC进行时,Eden区中所有存活的对象都会被复制到To Survivor区,而在From Survivor区中,仍存活的对象会根据它们的年龄值决定去向,年龄值达到年龄阀值(默认为15,新生代中的对象每熬过一轮垃圾回收,年龄值就加1,GC分代年龄存储在对象的header中)的对象会被移到老年代中,没有达到阀值的对象会被复制到To Survivor区。接着清空Eden区和From Survivor区,新生代中存活的对象都在To Survivor区。接着, From Survivor区和To Survivor区会交换它们的角色,也就是新的To Survivor区就是上次GC清空的From Survivor区,新的From Survivor区就是上次GC的To Survivor区,总之,不管怎样都会保证To Survivor区在一轮GC后是空的。GC时当To Survivor区没有足够的空间存放上一次新生代收集下来的存活对象时,需要依赖老年代进行分配担保,将这些对象存放在老年代中。

老年代(Old)

       在新生代中经历了多次(具体看虚拟机配置的阀值)GC后仍然存活下来的对象会进入老年代中。老年代中的对象生命周期较长,存活率比较高,在老年代中进行GC的频率相对而言较低,而且回收的速度也比较慢。

永久代(Permanent)

       永久代存储类信息、常量、静态变量、即时编译器编译后的代码等数据,对这一区域而言,Java虚拟机规范指出可以不进行垃圾收集,一般而言不会进行垃圾回收。

Minor GC 和 Full GC的区别

       新生代GC(Minor GC):Minor GC指发生在新生代的GC,因为新生代的Java对象大多都是朝生夕死,所以Minor GC非常频繁,一般回收速度也比较快。当Eden空间不足以为对象分配内存时,会触发Minor GC。

老年代GC(Full GC/Major GC):Full GC指发生在老年代的GC,出现了Full GC一般会伴随着至少一次的Minor GC(老年代的对象大部分是Minor GC过程中从新生代进入老年代),比如:分配担保失败。Full GC的速度一般会比Minor GC慢10倍以上。当老年代内存不足或者显式调用System.gc()方法时,会触发Full GC。

时间: 2024-07-30 12:13:55

Java虚拟机:JVM内存分代策略的相关文章

第五章:JVM内存分代策略

① Java虚拟机根据对象存活的周期不同,把堆内存划分为几块,一般分为新生代.老年代和永久代(对HotSpot虚拟机而言),这就是JVM的内存分代策略. ②为什么要分代? 堆内存是虚拟机管理的内存中最大的一块,也是垃圾回收最频繁的一块区域,我们程序所有的对象实例都存放在堆内存中.给堆内存分代是为了提高对象内存分配和垃圾回收的效率.试想一下,如果堆内存没有区域划分,所有的新创建的对象和生命周期很长的对象放在一起,随着程序的执行,堆内存需要频繁进行垃圾收集,而每次回收都要遍历所有的对象,遍历这些对象

Java虚拟机学习:分代收集算法

摘要:当前商业虚拟机的垃圾收集都采用"分代收集"(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象的存活周期的不同将内存划分为几块.一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法.在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集.而老年代中因为对象存活率高.没有额外空间对它进行分配担保,就必须使用"标记-清理&qu

深入Java虚拟机——JVM内存详解

在C++中,程序员拥有每一个对象的所有权,但与此同时还肩负着释放对象内存空间的责任:而Java由于有了虚拟机的帮助,程序员拥有对象的所有权的同时不再需要释放对象的内存空间.由于是JVM自动进行对象内存的释放,所以内存泄漏和内存溢出的问题也很少出现. Java虚拟机在运行时将内存空间分成5个部分,分别是:方法区.虚拟机栈.本地方法栈.堆.程序计数器. 程序计数器 本质 程序计数器本质上是一块较小的内存空间. 作用 可以把程序计数器简单地看作是当前线程所执行的字节码的行号指示器. 字节码解释器在工作

深入理解Java虚拟机笔记---内存分配与回收策略

Java技术体系中的自动内存管理最终可以归结为自动化地解决了两个问题:给对象分配内存以及回收分配给对象的内存.对象的内存分配往大的方向上讲,就是在堆上分配,对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲(-XX:+UseTLAB,默认已开启),将按线程优先在TLAB上分配.少数情况下也可能会直接分配在老年代中,分配的规则并不是百分之百固定的,其细节取决于当前使用的是哪一种垃圾收集器组合,还有虚拟机中与内存相关的参数设置. 下面是几条主要的最普遍的内存分配规则: 1.对象优先在Ed

《深入理解Java虚拟机 JVM高级特性...》核心笔记

深入理解Java虚拟机 JVM高级特性与最佳实践(第二版) 核心笔记 JAVA 环境: JAVA虚拟机高级特性: 一:java内存区域与内存异常 一):运行数据区     1:程序计数器(Program Counter Register),也称"PC寄存器" A:用来指示需要执行哪条指令的.(在汇编语言中,CPU在得到指令之后,程序计数器便自动加1或者根据                    转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令.) B:由于在JVM中,多线程

Java虚拟机的内存管理

众所周知,Java程序员写的代码是没有办法控制Java对象的内存释放的,完全有JVM暗箱操作. 虽然程序员把内存的释放的任务都交给了Java虚拟机,但是并不代表Java程序就不存在内存泄漏. 反而,某程度上,当出现内存泄漏,Debug会变得难度更大. 所以,Java程序员,有必要去了解Java虚拟机对于内存的管理以及垃圾回收的机制. Java虚拟机是如何判断一个对象可以回收? 当一个对象没有被任何其他所引用时,这个对象被Java虚拟机视为可回收. 早起的虚拟机,使用引用计数的方法判断对象是否可回

关于 Java虚拟机:内存处理与执行引擎

一.Java技术体系简介: Java技术体系包括以下几个组成部分: java程序设计语言 各种硬件平台上的java虚拟机 Class文件格式 Java API 类库 来自商业机构和开源社区的第三方类库 JDK(java Development Kit):包括java程序设计语言,java虚拟机,java API类库.JDK是用于支持java程序开发的最小环境. JRE(java Runtime Environment) 包括java API类库中的java SE API子集,java虚拟机.JR

Java虚拟机JVM简单理解

Java虚拟机JVM的作用: Java源文件(.java)通过编译器编译成.class文件,.class文件通过JVM中的解释器解释成特定机器上的机器代码,从而实现Java语言的跨平台. JVM的体系结构包含三个主要的子系统和一个内存区,分别是: 垃圾回收器:用于回收堆(heap)中无引用的对象. 类装载子系统:定位及导入二进制class文件,校验被导入类的正确性,为类变量分配初始化内存,以及帮助解析符号引用. 执行引擎:执行被转载类中的方法指令. 运行时数据区:又叫做虚拟机内存或Java内存.

Java虚拟机:内存模型详解

版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 我们都知道,当虚拟机执行Java代码的时候,首先要把字节码文件加载到内存,那么这些类的信息都存放在内存中的哪个区域呢?当我们创建一个对象实例的时候,虚拟机要为对象分配内存,Java虚拟机又是如何配分内存的呢?这些都涉及到Java虚拟机的内存划分机制,今天我们就来探究一下Java虚拟机的内存模型. Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途以及创建和销毁的时间,有的区域随