gc基本原理和内存溢出

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.youkuaiyun.com/buyaoshuohua1/article/details/74464397
垃圾回收机制
1. 内存的组成:堆(Heap)和非堆(Non-heap)内存。

堆是运行时数据区域,是由new分配的内存,因为不知道大小的,应该有程序自己来申请内存空间,所以由堆来分配是留给开发人员使用的;

非堆就是JVM留给自己用的。

2. JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC后调整堆的大小。(这个在后边jvm调优会用到)。

3. 看张图片:堆内存分配(跟后边说到的GC原理还有jvm调优参数相关联)

4. 非堆内存分配

JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

 

上边名词的定义和解释,其实跟接下来要说的垃圾回收机制采用的方法相关:

JVM里的GC(Garbage Collection)的算法有很多种,这里就说最常用的一种,分代收集算法。

5. 分代收集算法将内存分为几个区域,将不同生命周期的对象放在不同区域里:young generation,tenured generation和permanet generation。绝大部分的object被分配在young generation(生命周期短),并且大部分的object在这里die。当young generation满了之后,将引发minor collection(YGC)。在minor collection后存活的object会被移动到tenured generation(生命周期比较长)。最后,tenured generation满之后触发major collection。major collection(Full gc)会触发整个heap的回收,包括回收young generation。permanet generation区域比较稳定,主要存放classloader信息。

6. young generation有eden、2个survivor区域组成。其中一个survivor区域一直是空的,是eden区域和另一个survivor区域在下一次copy collection后(YGC)活着的object的目的地。object在survivo区域被复制直到转移到tenured区。

7. 我们要尽量减少 Full gc的次数(tenured generation一般比较大,收集的时间较长,频繁的Full gc会导致应用的性能收到严重的影响)。

8. 堆内存GC:JVM(采用分代回收的策略),用较高的频率对年轻的对象(young generation)进行YGC,而对老对象(tenured generation)较少(tenured generation 满了后才进行)进行Full GC。这样就不需要每次GC都将内存中所有对象都检查一遍。

9. 非堆内存不GC:GC不会在主程序运行期对PermGen Space进行清理,所以如果你的应用中有很多CLASS(特别是动态生成类,当然permgen space存放的内容不仅限于类)的话,就很可能出现PermGen Space错误。

至此:GC的执行流程基本就说完了。接下来,看一些jvm的配置参数,通过配置可以防止GC后出现卡顿的现象。

10. 再说一个项目中的问题:

promotion failed: 垃圾回收时promotion failed是个很头痛的问题,一般可能是两种原因产生,第一个原因是救助空间不够,救助空间里的对象还不应该被移动到年老代,但年轻代又有很多对象需要放入救助空间;第二个原因是年老代没有足够的空间接纳来自年轻代的对象;这两种情况都会转向Full GC,网站停顿时间较长。

再换一种说法:promontion faild产生的原因是EDEN空间不足的情况下将EDEN与From survivor中的存活对象存入To survivor区时,To survivor区的空间不足,再次晋升到old gen区,而old gen区内存也不够的情况下产生了promontion faild从而导致full gc.那可以推断出:eden+from survivor < old gen区剩余内存时,不会出现promontion faild的情况。即如下公式:

(Xmx-Xmn)*(1-CMSInitiatingOccupancyFraction/100)>=(Xmn-Xmn/(SurvivorRatior+2))这个不难理解。

进而推断出:
CMSInitiatingOccupancyFraction <=((Xmx-Xmn)-(Xmn-Xmn/(SurvivorRatior+2)))/(Xmx-Xmn)*100。

CMSInitiatingOccupancyFraction低于80%需要调整xmn或SurvivorRatior值。

11.网上推荐的jvm配置的最优方案(仅供参考)

-Xmx256M//最大堆大小

-Xms256M //初始堆大小

-Xmn96M //年轻代大小Sun官方推荐配置为整个堆的3/8

-XX:PermSize=500M //设置持久代(perm gen)初始值 非堆内存

-XX:MaxPermSize=500M //设置持久代最大值 --------XMX和XMS设置一样大,MaxPermSize和MinPermSize设置一样大,这样可以减轻伸缩堆大小带来的压力。

-Xss256K //每个线程的堆栈大小

-XX:+DisableExplicitGC //关闭System.gc(),免得程序员误调用gc方法影响性能

-XX:SurvivorRatio=1 //Eden区与Survivor区的大小比值(计算公式)

-XX:+UseConcMarkSweepGC //使用CMS内存收集(使用CMS的好处是用尽量少的新生代,经验值是128M-256M, 然后老生代利用CMS并行收集, 这样能保证系统低延迟的吞吐效率。 实际上cms的收集停顿时间非常的短,2G的内存, 大约20-80ms的应用程序停顿时间)

-XX:+UseParNewGC //设置年轻代为并行收集(使用CMS的好处是用尽量少的新生代,经验值是128M-256M, 然后老生代利用CMS并行收集, 这样能保证系统低延迟的吞吐效率。 实际上cms的收集停顿时间非常的短,2G的内存, 大约20-80ms的应用程序停顿时间)。

-XX:+CMSParallelRemarkEnabled // 降低标记停顿

-XX:+UseCMSCompactAtFullCollection //在FULL GC的时候,对年老代的压缩 消除碎片1

-XX:CMSFullGCsBeforeCompaction=0 // 多少次后进行内存压缩2

-XX:+CMSClassUnloadingEnabled

-XX:LargePageSizeInBytes=128M //内存页的大小不可设置过大, 会影响Perm的大小

-XX:+UseFastAccessorMethods //原始类型的快速优化

-XX:+UseCMSInitiatingOccupancyOnly //使用手动定义初始化定义开始CMS收集,禁止hostspot自行触发CMS GC

-XX:CMSInitiatingOccupancyFraction=80 //使用cms作为垃圾回收 使用80%后开始CMS收集

-XX:SoftRefLRUPolicyMSPerMB=0 //每兆堆空闲空间中SoftReference的存活时间

-XX:+PrintClassHistogram

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-XX:+PrintHeapAtGC //打印GC前后的详细堆栈信息
————————————————

垃圾回收的基本原理算法思路都是一致的:把所有对象组成一个集合,或可以理解为树状结构,从树根开始找,只要可以找到的都是活动对象,如果找不到,这个对象就被回收了

垃圾回收分为两个阶段:

标记 --> 压缩标记的过程,其实就是判断对象是否可达的过程。当所有的根都检查完毕后,堆中将包含可达(已标记)与不可达(未标记)对象。标记完成后,进入压缩阶段。在这个阶段中,垃圾回收器线性的遍历堆,以寻找不可达对象的连续内存块。并把可达对象移动到这里以节约内存空间。

Java有了GC同样会出现内存泄露问题

1.静态集合类像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,所有的对象Object也不能被释放,因为他们也将一直被Vector等应用着。

2.各种连接,数据库连接,网络连接,IO连接等没有显示调用close关闭,不被GC回收导致内存泄露。

3.监听器的使用,在释放对象的同时没有相应删除监听器的时候也可能导致内存泄露。

垃圾回收器负责回收所有无任何引用对象的内存空间。

注意:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身。
版权声明:本文为优快云博主「二缺和傻宝宝」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/buyaoshuohua1/article/details/74464397

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值