欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JVM简介堆中新生代老年代浅析

程序员文章站 2022-05-25 20:17:52
一、JVM内存结构由程序计数器、堆、栈、本地方法栈、方法区等部分组成。1)程序计数器 几乎不占有内存。用于取下一条执行的指令。2)堆 所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制。堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,最后 ......

一、jvm内存结构由程序计数器、堆、栈、本地方法栈、方法区等部分组成。
1)程序计数器
几乎不占有内存。用于取下一条执行的指令。
2)堆
所有通过new创建的对象的内存都在堆中分配,其大小可以通过-xmx和-xms来控制。堆被划分为新生代和旧生代,新生代又被进一步划分为eden和survivor区,最后survivor由fromspace和tospace组成。
一般情况将新生代分为eden ,两块survivor区域;
新生代。新建的对象都是用新生代分配内存,eden空间不足的时候,会把存活的对象转移到survivor中,新生代大小可以由-xmn来控制,也可以用-xx:survivorratio来控制eden和survivor的比例旧生代。用于存放新生代中经过多次垃圾回收仍然存活的对象。
3)栈
每个线程执行每个方法的时候都会在栈中申请一个栈帧,每个栈帧包括局部变量区和操作数栈,用于存放此次方法调用过程中的临时变量、参数和中间结果。
4)本地方法栈
用于支持native方法的执行,存储了每个native方法调用的状态。
5)方法区
存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。jvm用永久代(permanetgeneration)来存放方法区,(在jdk的hotspot虚拟机中,可以认为方法区就是永久代,但是在其他类型的虚拟机中,没有永久代的概念,有关信息可以看周志明的书)可通过-xx:permsize和-xx:maxpermsize来指定最小值和最大值。

二、jvm垃圾回收机制
jvm分别对新生代和旧生代采用不同的垃圾回收机制
新生代的gc:
新生代通常存活时间较短,因此基于复制算法来进行回收,所谓复制算法就是扫描出存活的对象,并复制到一块新的完全未使用的空间中,对应于新生代,就是在eden和其中一个survivor,复制到另一个之间survivor空间中,然后清理掉原来就是在eden和其中一个survivor中的对象。新生代采用空闲指针的方式来控制gc触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发gc。当连续分配对象时,对象会逐渐从eden到 survivor,最后到老年代。

用javavisualvm来查看,能明显观察到新生代满了后,会把对象转移到旧生代,然后清空继续装载,当旧生代也满了后,就会报outofmemory的异常。

旧生代与新生代不同,对象存活的时间比较长,比较稳定,因此采用标记(mark)算法来进行回收,所谓标记就是扫描出存活的对象,然后再进行回收未被标记的对象,回收后对用空出的空间要么进行合并,要么标记出来便于下次进行分配,总之就是要减少内存碎片带来的效率损耗。

三、gc堆

java 中的堆是 jvm 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。
在 java 中,堆被划分成两个不同的区域:新生代 ( young )、老年代 ( old )。新生代 ( young ) 又被划分为三个区域:eden、from survivor、to survivor。
这样划分的目的是为了使 jvm 能够更好的管理堆内存中的对象,包括内存的分配以及回收。
堆的内存模型大致为:

JVM简介堆中新生代老年代浅析


从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –xms、-xmx 来指定。
默认的,新生代 ( young ) 与老年代 ( old ) 的比例的值为 1:2 ( 该值可以通过参数 –xx:newratio 来指定),即:新生代 ( young ) = 1/3 的堆空间大小。老年代 ( old ) = 2/3 的堆空间大小。其中,新生代 ( young )被细分为 eden 和 两个 survivor 区域,这两个 survivor 区域分别被命名为 from 和 to,以示区分。
默认的,edem : from : to = 8 :1 : 1 ( 可以通过参数–xx:survivorratio 来设定 ),即: eden = 8/10 的
新生代空间大小,from = to = 1/10 的新生代空间大小。
jvm 每次只会使用 eden 和其中的一块 survivor 区域来为对象服务,所以无论什么时候,总是有一块survivor区域是空闲着的。
因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。

四、jvm 参数选项
下面只列举其中的几个常用和容易掌握的配置选项:
-xms
初始堆大小。如:-xms256m

-xmx
最大堆大小。如:-xmx512m

-xmn
新生代大小。通常为 xmx 的 1/3 或 1/4。新生代 = eden + 2 个 survivor 空间。实际可用空间为 = eden + 1 个 survivor,即 90%

-xss
jdk1.5+ 每个线程堆栈大小为 1m,一般来说如果栈不是很深的话, 1m 是绝对够用了的。

-xx:newratio
新生代与老年代的比例,如 –xx:newratio=2,则新生代占整个堆空间的1/3,老年代占2/3

-xx:survivorratio
新生代中 eden 与 survivor 的比值。默认值为 8。即 eden 占新生代空间的 8/10,另外两个 survivor 各占 1/10

-xx:permsize
永久代(方法区)的初始大小

-xx:maxpermsize
永久代(方法区)的最大值

-xx:+printgcdetails
打印 gc 信息

-xx:+heapdumponoutofmemoryerror
让虚拟机在发生内存溢出时 dump 出当前的内存堆转储快照,以便分析用