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的主要内容,如果未能解决你的问题,请参考以下文章