再回首万恶的JVM GC

Posted

tags:

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

GC(普通的理解):用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间。


 1.Java堆中各代分布

Young:主要是用来存放新生的对象。

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

Permanent:是指内存的永久保存区域,主要存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域. 它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。


2. JVM 使用的GC算法是什么?

分代收集。

即将内存分为几个区域,将不同生命周期的对象放在不同区域里;

在GC收集的时候,频繁收集生命周期短的区域(Young area);

比较少的收集生命周期比较长的区域(Old area);

基本不收集的永久区(Perm area)。


3. GC 和 Full GC 有什么区别?

GC(或Minor GC):收集 生命周期短的区域(Young area)。

Full GC (或Major GC):收集生命周期短的区域(Young area)和生命周期比较长的区域(Old area)。

他们的收集算法不同,所以使用的时间也不同。 GC 效率也会比较高,我们要尽量减少 Full GC 的次数。 当显示调用System.gc() 时,gc does a full collection(both young generation and tenured generation).


4.垃圾回收器什么时候会被创建:

垃圾回收器会在下面两种假设(hypotheses)成立的情况下被创建:

1.大多数对象会很快变得不可达

2.只有很少的由老对象(创建时间较长的对象)指向新生对象的引用




   开发人员无法直接在程序代码中清理内存,而是由垃圾回收器自动寻找不必要的垃圾对象,并且清理掉他们。一般来说是可以试图,将对象设置null或者调用system.gc(),然而设置Null是个好习惯,但是,调用system.gc()只是在向JVM说明,你可以来收集了至于要不要GC还是说不准,可以说没任何实际意义,反而,会调用fullGC,使得GC效率更加低下


新生代(Young generation): 绝大多数最新被创建的对象会被分配到这里,由于大部分对象在创建后会很快变得不可到达,所以很多对象被创建在新生代,然后消失。对象从这个区域消失的过程我们称之为”minor GC“。


老年代(Old generation): 对象没有变得不可达,并且从新生代中存活下来,会被拷贝到这里。其所占用的空间要比新生代多。也正由于其相对较大的空间,发生在老年代上的GC要比新生代少得多。对象从老年代中消失的过程,我们称之为”major GC“(或者”full GC“)


持久代( permanent generation )也被称为方法区(method area)。他用来保存类常量以及字符串常量,class,jar包等。因此,这个区域不是用来永久的存储那些从老年代存活下来的对象。这个区域也可能发生GC。并且发生在这个区域上的GC事件也会被算为major GC。


新生代的构成


为了更好地理解GC,我们现在来学习新生代,新生代是用来保存那些第一次被创建的对象,他可以被分为三个空间


1. 一个伊甸园空间(Eden )

 2.两个幸存者空间(Survivor )

一共有三个空间,其中包含两个幸存者空间。每个空间的执行顺序如下:


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

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

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

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

在以上的步骤中重复几次依然存活的对象,就会被移动到老年代。

如果你仔细观察这些步骤就会发现,其中一个幸存者空间必须保持是空的。如果两个幸存者空间都有数据,或者两个空间都是空的,那一定标志着你的系统出现了某种错误。


Java2增强了内存管理功能,增加了一个java.lang.ref包,其中定义了三种引用类。这三种引用类分别为SoftReference、WeakReference和 PhantomReference.通过使用这些引用类,程序员可以在一定程度与GC进行交互,以便改善GC的工作效率。这些引用类的引用强度介于可达对象和不可达对象之间。 



5.堆设置 

-Xms :初始堆大小 

-Xmx :最大堆大小 

-XX:NewSize=n :设置年轻代大小 

-XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4 

-XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 

-XX:MaxPermSize=n :设置持久代大小 

收集器设置 

-XX:+UseSerialGC :设置串行收集器 

-XX:+UseParallelGC :设置并行收集器 

-XX:+UseParalledlOldGC :设置并行年老代收集器 

-XX:+UseConcMarkSweepGC :设置并发收集器 

垃圾回收统计信息 

-XX:+PrintGC 

-XX:+PrintGCDetails 

-XX:+PrintGCTimeStamps 

-Xloggc:filename 

并行收集器设置 

-XX:ParallelGCThreads=n :设置并行收集器收集时使用的CPU数。并行收集线程数。 

-XX:MaxGCPauseMillis=n :设置并行收集最大暂停时间 

-XX:GCTimeRatio=n :设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n) 

并发收集器设置 

-XX:+CMSIncrementalMode :设置为增量模式。适用于单CPU情况。 

-XX:ParallelGCThreads=n :设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。


6. 例子:Heap size 设置

场景:在JAVA_HOME下demo/jfc/SwingSet2/目录下执行下面的命令:

    java -jar -Xmn4m -Xms16m -Xmx16m SwingSet2.jar


7. 常见的内存泄露错误

很多开发人员都碰到过java.lang.OutOfMemoryError的错误。这种错误又分两种:java.lang.OutOfMemoryError: Java heap space和java.lang.OutOfMemoryError: PermGen space。引起这种错误的原因可能是程序问题,也可能是是JVM参数配置问题引起的。若是参数问题,前者可以同过配置-Xms和-Xmx参数来设置,而后者可以通过配置 -XX:PermSize和-XX:MaxPermSize来设置。


本文主要是搜集和整理:

http://www.importnew.com/1993.html

http://blog.csdn.net/winniepu/article/details/4829087

以上是关于再回首万恶的JVM GC的主要内容,如果未能解决你的问题,请参考以下文章

再回首Java一周记

再回首Java第六天

Idea登录页面再回首

Idea登录页面再回首

第一个Python程序----再回首恍然入门

再回首之关键字static