JAVA 垃圾回收机制GC

JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象。

GC的工作目的:在堆中,找到已经无用的对象,并把这些对象占用的空间收回使其可以重新利用.

JVM堆
(1) 新域:存储所有新成生的对象
(2) 旧域:新域中的对象,经过了一定次数的GC循环后,被移入旧域
(3)永久域:存储类和方法对象,从配置的角度看,这个域是独立的,不包括在JVM堆内。默认为4M。

新域会被分为3个部分:
1.第一个部分叫Eden。
2.另两个部分称为辅助生存空间(幼儿园),一个称为A空间(From sqace),一个称为B空间(To Space)。

对于新生成的对象,都放在Eden中;当Eden充满时(小孩太多 了),GC将开始工作,首先停止应用程序的运行,开始收集垃圾,把所有可找到的对象都复制到A空间中,一旦当A空间充满,GC就把在A空间中可找到的对象 都复制到B空间中(会覆盖原有的存储对象),当B空间满的时间,GC就把在B空间中可找到的对象都复制到A空间中,AB在这个过程中互换角色,在活动对象经过一定次数的GC操作后,这些活动对象就会被放到旧域中。

对于旧域,采用的是tracing算法的一种,称为标记-清除-压缩收 集器,注意,这有一个压缩,这是个开销挺大的操作。
垃圾回收主要是对Young Generation块和Old Generation块内存进行回收,YG用来放新产生的对象,经过几次回收还没回收掉的对象往OG中移动,
对YG进行垃圾回收又叫做MinorGC,对 OG垃圾回收又叫MajorGC,两块内存回收互不干涉。

经验:
1.JVM堆的大小决定了GC的运行时间。如果JVM堆的大小超过一定的限度,那么GC的运行时间会很长。
2.对象生存的时间越长,GC需要的回收时间也越长,影响了回收速度。
3.大多数对象都是短命的,所以,如果能让这些对象的生存期在GC的一次运行周期内,wonderful!
4.应用程序中,建立与释放对象的速度决定了垃圾收集的频率。
5.如果GC一次运行周期超过3-5秒这会很影响应用程序的运行,应该减少JVM堆的大小了。
6.通常情况下,JVM堆的大小应为物理内存的80%。

内存溢出
jvm内存溢出的几种情况。

OutOfMemoryError:Java heap space
jvm的堆内存溢出,在jvm中98%的内存都在等待GC回收,且Heap Size不足2%的可用空间时,将抛出此错误,对应的解决办法增加-xmx和-xms的大小。

OutOfMemoryError:PermGen Space
jvm的非堆内存溢出,可能情况有如下几种

如果web app下用大量的第三方jar,其总大小超过非堆内存的最大值,会抛出此异常
项目拥有太多的class文件,恰好maxPermSize设置的小于class总大小,会抛出此异常
tomcat部署的时候,不会清理前面加载的环境,只会将context更改为新部署的代码,所以非堆内存越来越多
OutOfMemoryError:unable to new native thread:
这是jvm无法创建新线程,这个错误比较少见,也比较奇怪。主要是jvm与内存的比例有关。这种怪事因为jvm已经被系统分配了大量的内存。并且它至少占用可用内存的一半空间。可以尝试重启tomcat或加大非堆内存对应的值。

猜你喜欢

转载自blog.csdn.net/inventecsh/article/details/85059948