JAVA垃圾收集器之Serial收集器

1、特点

Serial收集器是JAVA虚拟机中最基本、历史最悠久的收集器,在JDK 1.3.1之前是JAVA虚拟机新生代收集的唯一选择。Serial收集器是一个单线程的收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。

要是服务器每运行一个小时就会暂停5分钟,老板会有什么样的心情?

2、发展

从JDK 1.3开始,一直到现在还没正式发布的JDK 1.7,HotSpot虚拟机开发团队为消除或减少工作线程因内存回收而导致停顿的努力一直在进行着,从Serial收集器到Parallel收集器,再到Concurrent
Mark Sweep(CMS收集器)现在还未正式发布的Garbage First(G1)收集器,我们看到了一个个越来越优秀(也越来越复杂)的收集器的出现,用户线程的停顿时间在不断缩短,但是仍然没有办法完全消除。

3、现状

Serial收集器到现在为止,它依然是JAVA虚拟机运行在Client模式下的默认新生代收集器。它也有着优于其他收集器的地方:简单而高效(与其他收集器的单线程比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。在用户的桌面应用场景中,分配给虚拟机管理的内存一般来说不会很大,收集几十兆甚至一两百兆的新生代(仅仅是新生代使用的内存,桌面应用基本上不会再大了),停顿时间完全可以控制在几十毫秒最多一百多毫秒以内,只要不是频繁发生,这点停顿是可以接受的。所以,Serial收集器对于运行在Client模式下的虚拟机来说是一个很好的选择。

4、代码和示例(固定JAVA虚拟机的大小)

package com.gc;

import java.util.ArrayList;

import java.util.List;

/**

* 简单的JAVA虚拟机内存回收,serial收集器的使用

* 参数:-Xms30m -Xmx30m-Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails

* @author 范芳铭

*/

public class EasySerial {

public byte[] placeHolder =new byte[64 * 1024]; //占位符

public static voidmain(String[] args) throws Exception{

outOfMemoryByFixSize();

}

/**

* 固定JAVA虚拟机的大小

* 参数:-Xms30m -Xmx30m-Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails

* @author 范芳铭

*/

private static voidoutOfMemoryByFixSize() throws Exception{

List<EasySerial>list = new ArrayList<EasySerial>();

while(true){

EasySerialserial = new EasySerial();

list.add(serial);

Thread.sleep(10);//停顿10毫秒

}

}

/**

* JAVA虚拟机的大小适当可扩展,其中Xms30m,Xmx40m

* 参数:-Xms30m -Xmx40m-XX:+UseSerialGC -XX:+PrintGCDetails

* @author 范芳铭

*/

private static voidoutOfMemoryByExpansionSize() throws Exception{

List<EasySerial>list = new ArrayList<EasySerial>();

while(true){

EasySerialserial = new EasySerial();

list.add(serial);

Thread.sleep(10);//停顿10毫秒

}

}

}

参数:-Xms30m -Xmx30m-Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails

-XX:+UseSerialGC的是Serial收集器,Xms30m -Xmx30m
指定了JAVA虚拟机的固定大小为30M,-Xmn10m
指JAVA新生代的空间为10M。

运行结果如下:

[GC [DefNew: 8137K->1023K(9216K),0.0054427 secs] 8137K->8019K(29696K), 0.0054763 secs] [Times: user=0.00sys=0.00, real=0.01 secs]

[GC [DefNew: 9175K->963K(9216K),0.0056574 secs] 16170K->16151K(29696K), 0.0056820 secs] [Times: user=0.00sys=0.00, real=0.00 secs]

[GC [DefNew: 9149K->9149K(9216K),0.0000197 secs][Tenured: 15188K->20441K(20480K), 0.0065753 secs]24337K->24284K(29696K), [Perm : 2086K->2086K(12288K)], 0.0066451 secs][Times: user=0.00 sys=0.00, real=0.01 secs]

[Full GC [Tenured:20441K->20441K(20480K), 0.0038802 secs] 29570K->29537K(29696K), [Perm :2086K->2086K(12288K)], 0.0039147 secs] [Times: user=0.00 sys=0.00, real=0.00secs]

[Full GC [Tenured:20441K->20436K(20480K), 0.0061865 secs] 29537K->29532K(29696K), [Perm :2086K->2084K(12288K)], 0.0062235 secs] [Times: user=0.00 sys=0.00, real=0.01secs]

Exception in thread "main"java.lang.OutOfMemoryError: Java heap space

atcom.gc.EasySerial.<init>(EasySerial.java:12)

atcom.gc.EasySerial.outOfMemoryByFixSize(EasySerial.java:25)

atcom.gc.EasySerial.main(EasySerial.java:14)

Heap

def new generation   total 9216K, used 9152K [0x03bd0000,0x045d0000, 0x045d0000)

eden space 8192K, 100% used [0x03bd0000, 0x043d0000, 0x043d0000)

from space 1024K,  93% used[0x043d0000, 0x044c00f0, 0x044d0000)

to   space 1024K,   0% used [0x044d0000, 0x044d0000, 0x045d0000)

tenured generation   total 20480K, used 20436K [0x045d0000,0x059d0000, 0x059d0000)

the space 20480K,  99% used[0x045d0000, 0x059c52b8, 0x059c5400, 0x059d0000)

compacting perm gen  total 12288K, used 2105K [0x059d0000,0x065d0000, 0x099d0000)

GC [DefNew :是在新生代的回收,能够很清楚的看到新生代的空间被迅速用完。

Full GC [Tenured是在老年代的全GC回收,空间也很快用完,然后出现OutOfMemoryError错误,导致系统崩溃。

5、代码和示例(可扩展JAVA虚拟机大小)

package com.gc;

import java.util.ArrayList;

import java.util.List;

/**

* 简单的JAVA虚拟机内存回收,serial收集器的使用

* 参数:-Xms30m -Xmx30m-Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails

* @author 范芳铭

*/

public class EasySerial {

public byte[] placeHolder =new byte[64 * 1024]; //占位符

public static voidmain(String[] args) throws Exception{

outOfMemoryByExpansionSize();

}

/**

* 固定JAVA虚拟机的大小

* 参数:-Xms30m -Xmx30m-Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails

* @author 范芳铭

*/

private static voidoutOfMemoryByFixSize() throws Exception{

List<EasySerial>list = new ArrayList<EasySerial>();

while(true){

EasySerialserial = new EasySerial();

list.add(serial);

Thread.sleep(10);//停顿10毫秒

}

}

/**

* JAVA虚拟机的大小适当可扩展,其中Xms30m,Xmx40m

* 参数:-Xms30m -Xmx40m-XX:+UseSerialGC -XX:+PrintGCDetails

* @author 范芳铭

*/

private static voidoutOfMemoryByExpansionSize() throws Exception{

List<EasySerial>list = new ArrayList<EasySerial>();

while(true){

EasySerialserial = new EasySerial();

list.add(serial);

Thread.sleep(10);//停顿10毫秒

}

}

}

参数:-Xms30m -Xmx30m-Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails

-XX:+UseSerialGC的是Serial收集器,Xms30m –Xmx40m
指定了JAVA虚拟机的大小可以从30M提升到40M,没有强制指定JAVA新生代的空间大小。

运行后情况:

[GC [DefNew: 1986K->128K(2112K),0.0011191 secs] 27809K->27808K(30528K), 0.0011425 secs] [Times: user=0.00sys=0.01, real=0.00 secs]

[GC [DefNew: 1989K->131K(2112K),0.0011326 secs][Tenured: 29536K->29539K(29568K), 0.0032603 secs]29669K->29667K(31680K), [Perm : 2086K->2086K(12288K)], 0.0044714 secs][Times: user=0.00 sys=0.00, real=0.00 secs]

[GC [DefNew: 2562K->192K(2880K),0.0024077 secs] 32102K->32100K(40704K), 0.0024426 secs] [Times: user=0.00sys=0.00, real=0.00 secs]

[GC [DefNew: 2755K->192K(2880K),0.0015362 secs] 34663K->34662K(40704K), 0.0015731 secs] [Times: user=0.00sys=0.00, real=0.00 secs]

[GC [DefNew: 2755K->192K(2880K),0.0015842 secs] 37224K->37223K(40704K), 0.0016187 secs] [Times: user=0.00sys=0.00, real=0.00 secs]

[GC [DefNew: 2755K->2755K(2880K),0.0000144 secs][Tenured: 37030K->37799K(37824K), 0.0039907 secs]39786K->39784K(40704K), [Perm : 2086K->2086K(12288K)], 0.0040547 secs][Times: user=0.00 sys=0.00, real=0.00 secs]

[Full GC [Tenured:37799K->37799K(37824K), 0.0032501 secs] 40554K->40553K(40704K), [Perm :2086K->2086K(12288K)], 0.0032940 secs] [Times: user=0.00 sys=0.00, real=0.00secs]

[Full GC [Tenured:37799K->37792K(37824K), 0.0107478 secs] 40553K->40546K(40704K), [Perm :2086K->2084K(12288K)], 0.0107782 secs] [Times: user=0.02 sys=0.00, real=0.01secs]

Exception in thread "main"java.lang.OutOfMemoryError: Java heap space

atcom.gc.EasySerial.<init>(EasySerial.java:12)

atcom.gc.EasySerial.outOfMemoryByExpansionSize(EasySerial.java:39)

atcom.gc.EasySerial.main(EasySerial.java:14)

Heap

def new generation   total 2880K, used 2810K [0x03ca0000,0x03fb0000, 0x03fb0000)

eden space 2624K,  99% used[0x03ca0000, 0x03f2e8e8, 0x03f30000)

from space 256K,  75% used[0x03f70000, 0x03fa0030, 0x03fb0000)

to   space 256K,   0% used [0x03f30000, 0x03f30000, 0x03f70000)

tenured generation   total 37824K, used 37792K [0x03fb0000,0x064a0000, 0x064a0000)

the space 37824K,  99% used[0x03fb0000, 0x064982e0, 0x06498400, 0x064a0000)

compacting perm gen  total 12288K, used 2105K [0x064a0000,0x070a0000, 0x0a4a0000)

the space 12288K,  17% used [0x064a0000, 0x066ae4a8, 0x066ae600,0x070a0000)

其他的内容和固定大小基本一致,多出来一种情况:

[GC [DefNew: 2755K->2755K(2880K),0.0000144 secs][Tenured: 37030K->37799K(37824K), 0.0039907 secs]39786K->39784K(40704K), [Perm : 2086K->2086K(12288K)], 0.0040547 secs][Times: user=0.00 sys=0.00, real=0.00 secs]

这个是对新生代,老年代,永久代都进行了次级垃圾回收。

时间: 2024-07-30 08:07:27

JAVA垃圾收集器之Serial收集器的相关文章

JAVA垃圾收集器之ParNew收集器

1.特点 ParNew收集器是JAVA虚拟机中垃圾收集器的一种.它是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数(例如:-XX:SurvivorRatio.-XX:PretenureSizeThreshold.-XX:HandlePromotionFailure等).收集算法.Stop The World.对象分配规则.回收策略等都与Serial收集器一致. 2.现状 ParNew是许多运行在Server模式下的虚拟机中首选的

JAVA垃圾收集器之CMS收集器

1.特点 CMS收集器是JAVA虚拟机中垃圾收集器的一种.它运行在JAVA虚拟机的老年代中.CMS是(Concurrent MarkSweep)的首字母缩写.CMS收集器是一种以获取最短回收停顿时间为目标的收集器.比较适用于互联网等场合,可能是互联网中最重要的收集器模式: 2.优点 由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程是与用户线程一起并发地执行的.因此CMS是一款优秀的收集器,具备了并发收集.低停顿的优点

JAVA垃圾收集器之Serial Old收集器

Serial Old收集器是JAVA虚拟机中垃圾收集器的一种,它是Serial收集器的老年代版本,它同样是一个单线程收集器,使用"标记-整理"算法.这个收集器的主要也是在目前的JAVA的Client模式下的虚拟机使用.如果在Server模式下,它主要还有两大用途:一个是在JDK 1.5及之前的版本中与Parallel Scavenge收集器搭配使用,另外一个就是作为CMS收集器的后备预案.如果CMS收集器出现Concurrent Mode Failure,则Serial Old收集器将

JAVA垃圾收集器之Parallel Scavenge收集器

Parallel Scavenge收集器是JAVA虚拟机中垃圾收集器的一种.和ParNew收集器类似,是一个新生代收集器.使用复制算法的并行多线程收集器. 1.特点 Parallel Scavenge收集器的关注点与其他收集器不同, ParallelScavenge收集器的目标则是达到一个可控制的吞吐量(Throughput).所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间),虚拟机总共运行了100分钟,

JVM垃圾收集器-Serial收集器

今天我给大家分享的是Serial收集器,垃圾收集器就是内存回收的具体实现.Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商,不同的版本的虚拟机所提供的垃圾收集器都可能会有很大的差别,并且一般都会提供参数供用户根据自己的应用特点和要求组合出各个年代所使用的收集器,这里讨论的收集器基于Sun HotSpot虚拟机1.6版Update22,这个虚拟机包含的所有的收集器如图所示. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ?上图展示了7种作用

Java垃圾收集器之--Garbage-First Collector

简介       Garbage-First(G1)垃圾收集器全面支持JDK7 Upate 4及后续版本.G1收集器是一个服务器形式(server-style)的垃圾收集器,主要用于内存大.多处理器的机器.当您想实现:与应用程序线程并发的执行全局标记,并且有高吞吐量.面向整个堆操作时,它可以满足您高可用性及GC暂停时间的要求. 此举可有效防止中断(GC时的暂停时间)与堆或者实时数据大小成比例增涨. 技术 G1收集器通过如下技术来实现高性能和低暂停时间: 堆被划分成一组相同大小的堆区域(heap

JAVA垃圾收集器之概说

1.垃圾收集器的组合 JAVA垃圾收集器一共有7个,减去还没有正式大规模使用的G1,还有6个,其中新生代3个,老生代3个. 因为垃圾收集器都是一组一组的工作,这6个收集器一共构成了5中使用模式. 参数 描述 -XX:+UseSerialGC Jvm运行在Client模式下的默认值,打开此开关后,使用Serial + Serial Old的收集器组合进行内存回收 -XX:+UseParNewGC 打开此开关后,使用ParNew + Serial Old的收集器进行垃圾回收 -XX:+UseConc

JAVA垃圾收集器之Parallel Old收集器

Parallel Old收集器是JAVA虚拟机中垃圾收集器的一种.和Serial Old收集器一样,工作在JAV虚拟机的老年代.这种垃圾收集器使用多线程和"标记-整理"算法.它在JDK 1.6中才开始提供. 在注重吞吐量及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器. 1.运行代码 package com.gc; import java.util.ArrayList; import java.util.List; /** * 简

JVM垃圾收集器-Serial Old收集器,Parallel Old收集器

Serial Old收集器 ? ? ? Serial Old收集器是Serial收集器的老年代版本,它是一个单线程收集器,使用"标记-整理"算法.这个收集器的主要意义也是被Client模式下的虚拟机使用.在server模式下,它主要还有两大用途:一个是在JDK1.5及之前的版本中与Parallel Scavenge收集器搭配使用,另外一个就是作为CMS收集器的后备元,在并发收集发生 Concurrent Mode Failure的时候使用.? ? ??? ? Parallel Old收