JVM堆内存即GC介绍联合Hadoop

Posted 互联网底层人员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM堆内存即GC介绍联合Hadoop相关的知识,希望对你有一定的参考价值。

JVM


提示:后续会更新JVM内存优化,api接口优化,监测内存使用

文章目录


一、JVM模型

JVM GC(垃圾回收机制)

在学习Java GC 之前,我们需要记住一个单词:stop-the-world 。它会在任何一种GC算法中发生。stop-the-world 意味着JVM因为需要执行GC而停止了应用程序的执行。当stop-the-world 发生时,除GC所需的线程外,所有的线程都进入等待状态,直到GC任务完成。GC优化很多时候就是减少stop-the-world 的发生。

1、JVM GC回收哪个区域内的垃圾?

JVM GC只回收堆区和方法区内的对象。而栈区的数据,在超出作用域后会被JVM自动释放掉,所以其不在JVM GC的管理范围内。


2、与Hadoop作业有什么关系?

我们在执行Mapreduce作业时,经常会碰到map任务不进行,或者reduce任务不进行了,卡在一个进度中。
因为每一次的map的输出都是一个新的对象,在内存分配少时(默认是1GB)且数据量为GB级别时会频繁发生GC,而且进程间(mapreduce是多进程,spark是多线程)会发生资源抢占,当高并发的job并发执行时即使开启FullGC(也无法清除掉堆对象因为单个进程还没有结束)且堆内存的不断增大,就会发生jvmpause异常(FULLGC执行的太过频繁这时程序会暂停,且CPU负担加重,若此时宕机或者程序卡住就会抛出sockettimeout异常或者60000ms内没有接收到新的数据),如果需要解决掉这个问题只能 提升单个节点的内存或者增加单个job任务的内存或者增加节点数。

3、JVM GC怎么判断对象可以被回收了?

· 对象没有引用

· 作用域发生未捕获异常

· 程序在作用域正常执行完毕

· 程序执行了System.exit()

· 程序发生意外终止(被杀线程等)

在Java程序中不能显式的分配和注销缓存,因为这些事情JVM都帮我们做了,那就是GC。

二、堆区内存的介绍

1.模型图


堆区分为新生代区和老年代区
新生代区又分为Eden(伊甸园区),S0和S1(幸存者区)
老年代区则独自为一区
比例为1:2 老年代区的空间比新生代大一倍

2.YGC

YGC(又名为小GC)
当新的对象来到堆区时,会首先进入到伊甸园区,如果伊甸园区的内存不够存放就会发生依次YGC,伊甸园内不需要的对象会被清理,若还有一些对象需要继续使用则会进入幸存者区。
若幸存者区已满或者放不下时,会直接进入老年代区,而幸存者区内的对象若存在时间过长且未被清理时,仍然会进入老年代区。


3.FULLGC

当老年代区已满或者存放不下内存时,会发生依次FULLGC,对所有的区都进行依次垃圾清除。FULLGC是最花销时间最大的GC,如果想要保证程序运行流程请务必减少FULLGC的次数,最好的方式就是加大内存的空间。

三. 总流程

1、绝大多数刚刚被创建的对象会存放在伊甸园空间(Eden)。

2、在伊甸园空间执行第一次GC(YGC)之后,存活的对象被移动到其中一个幸存者空间(Survivor)。

3、此后,每次伊甸园空间执行GC后,存活的对象会被堆积在同一个幸存者空间。

4、当一个幸存者空间饱和,还在存活的对象会被移动到另一个幸存者空间。然后会清空已经饱和的哪个幸存者空间。

5、在以上步骤中重复N次(N = MaxTenuringThreshold(年龄阀值设定,默认15))依然存活的对象,就会被移动到老年代。

从上面的步骤可以发现,两个幸存者空间,必须有一个是保持空的。如果两个两个幸存者空间都有数据,或两个空间都是空的,那一定是你的系统出现了某种错误。

我们需要重点记住的是,对象在刚刚被创建之后,是保存在伊甸园空间的(Eden)。那些长期存活的对象会经由幸存者空间(Survivor)转存到老年代空间(Old generation)。

也有例外出现,对于一些比较大的对象(需要分配一块比较大的连续内存空间)则直接进入到老年代。一般在Survivor 空间不足的情况下发生。

以上是关于JVM堆内存即GC介绍联合Hadoop的主要内容,如果未能解决你的问题,请参考以下文章

JVM堆内存很富足时,为啥经常连续发生两次full GC

Linux查看某个服务JVM的GC和堆内存使用情况

jvm 03-java堆内存模型

JVM 参数调整

JVM GC总结

如果由于CMS gc算法中的关键内存碎片而无法分配内存会发生什么