对象进入堆内存时,堆内存具体的分配和回收步骤

堆内存具体的分配和回收步骤:

在这里插入图片描述

(1)进入Eden区, 区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。

(2)MinorGC会清除Eden区的游离对象(没有被GC Roots标记的对象),非垃圾对象(被GC Roots标记的对象)会被复制到SurvivorFrom区,这些对象的分代年龄为1(经历了1次GC)。

(3)Eden内存不够又触发了MinorGC,MinorGC又会和步骤(2)一样清理垃圾,From区也会被清理,没有被清理的对象会被复制到To区,清空Eden区和From区。ServicorTo 和ServicorFrom 互换,原ServivorTo 成为下一次GC 时的ServivorFrom区。

(4)重复(1)(2)(3)步骤如果对象的还没有被清理,分代年龄达15次,该对象就会被复制到老年代。

(5)老年代内存不够时会触发full GC清理整个堆空间—包括年轻代和老年代。会导致STW(stop the world)停止所有用户线程让GC专心回收垃圾,用户线程会出现短暂卡顿。JVM调优就是为了减少STW时间和降低full GC发生次数。

(6)如果full GC后还没有更多的空间放新对象就会发生OOM(内存溢出)。


名词解析:

各个区的内存分配:老年代占三分之二内存,年轻代占三分之一。假如有3Gjvm内存,老年代占2G,年轻代占1G,年轻代中的Eden占800M,Survivor区占200M,Survivor区中的From和To分别占100M。

Eden区:Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当Eden 区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。

SurvivorFrom区:上一次GC 的幸存者,作为这一次GC 的被扫描者。

SurvivorTo区: 保留了一次MinorGC 过程中的幸存者。

MinorGC 的过程:复制->清空->互换

老年代:主要存放应用程序中生命周期长的内存对象。

分代年龄:经历GC的次数

GC Roots
在这里插入图片描述

问:JVM的分代年龄为什么是15?

在这里插入图片描述
由对象头里的Mark Word可知,分代年龄为4bit,即最大为1111,即15。

问:内存泄漏和内存溢出的区别?

内存泄露 :是指程序在申请内存后,无法释放已申请的内存空间就造成了内存泄漏,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

内存溢出: 指程序申请内存时,没有足够的内存供申请者使用,所需要使用的空间比拥有的内存大内存不够使用所造成的内存溢出。

内存泄漏的解决方案:
1、物理对象(比如Connection对象和IO)用好之后要及时close。
2、大的对象用好后及时设置成null,以撤销强引用。
3、集合对象用好后及时clear。
4、别频繁使用String(或其它不变类)对象,这样容易产生内存碎片。

内存溢出的解决方案:
第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
第二步,检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误。
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。

猜你喜欢

转载自blog.csdn.net/weixin_41699562/article/details/104133710
今日推荐