目录
内存分配是指哪个区域?
jvm运行时内存分为程序计数器、虚拟机栈、本地方法栈、堆和方法区。其中计数器、虚拟机栈、本地方法栈几个区域随线程生和灭,栈帧在编译期就可知,每一个栈帧的分配大小基本在类结构确定下来时就已经定下来了,因此这几个区域的内存分配和回收基本是确定。jvm中内存分配和gc的重点区域就是堆了,堆存储的都是对象的实例,因此更详细地我们可以说这篇文章讨论的是对象内存分配和回收。
1.堆的区域划分
jvm将堆划分为了新生代(Young)和老年代(Old),可以通过-Xms20M、-Xmn10M来限制堆大小和新生代和老年代的大小,其中设置堆得大小为20M,其中10M分给新生代,剩下10M分给老年代。其中新生代中又将内存按照8:1:1的比例(通过-XX:SurvivorRatio=8设置)分为安全区(Eden)和幸存者区(from survivor和to survivor)
区域的作用
Eden区:对象初始化的地盘,用于小对象和存在时间短的对象。
Survivor区:Minor gc时将仍然存活且存活年龄未达到一定标准的对象放入这里。
老年代:存储大对象和存在时间长的对象。
2.两种gc
新生代gc:(Minor gc):指发生在新生代的内存回收动作,因为java对象大都有朝生夕灭的特点,所以这种gc比较频繁,一般回收速度也比较快。
老年代gc:(Full gc):指发生在老年代的内存回收动作,出现full gc往往伴随着至少一次的Minor gc。Full gc的速度一般比Minor gc的速度慢十倍。
新生代gc发生时进行的事情:
1)Eden 区活着的对象 + From Survivor 存储的对象被复制到 To Survivor ,如果装不下,则晋升到老年代;
2) 清空 Eden 和 From Survivor ;
3) 颠倒 From Survivor 和 To Survivor 的逻辑关系: From 变 To , To 变 From 。
3.区域之间的变化
区域之间的变化是由于新对象的生成和发生gc引起的。
Eden 到 Survivor:创建对象时,优先到Eden区进行,若Eden区内存不足,发生一次Minor gc,Eden区中的存活对象进入Survivor区
新生代到老年代:1.创建对象时,对象超过了预设大小(通过PretenureSizeThreshold进行设置),直接进入老年代
2.创建对象时,Eden区内存不足,发生一次Minor gc,存活的对象Survivor无法装下,进入老年代。若老年代 无法装下,先进行一次full gc。
3.每次进行一次Minor gc,Survivor区中的年龄增加一岁,到达十五岁时晋升到老年代(通过-XX: MaxTenuringThreshold设置)。
4.若Survivor区中的相同年龄所有对象大小的总和大于Survivor空间的一半,进入老年代。