java垃圾收集机制

5 篇文章 0 订阅
1 篇文章 0 订阅

一.何为垃圾()

1.1 、引用计数算法(Reference Counting)

  介绍:给对象添加一个引用计数器,每当一个地方引用它时,数据器加1;当引用失效时,计数器减1;计数器为0的即可被回收。

  优点:实现简单,判断效率高

  缺点:很难解决对象之间的相互循环引用(objA.instance = objB; objB.instance = objA)的问题,所以java语言并没有选用引用计数法管理内存

1.2 、可达性分析算法

在主流商用语言(如Java、C#)的主流实现中, 都是通过可达性分析算法来判定对象是否存活的: 通过一系列的称为 GC Roots 的对象作为起点, 然后向下搜索; 搜索所走过的路径称为引用链/Reference Chain, 当一个对象到 GC Roots 没有任何引用链相连时, 即该对象不可达, 也就说明此对象是不可用的, 如下图: Object5、6、7 虽然互有关联, 但它们到GC Roots是不可达的, 因此也会被判定为可回收的对象:

  • 在Java, 可作为GC Roots的对象包括:
    1. 方法区: 类静态属性引用的对象;
    2. 方法区: 常量引用的对象;
    3. 虚拟机栈(本地变量表)中引用的对象.
    4. 本地方法栈JNI(Native方法)中引用的对象。

注: 即使在可达性分析算法中不可达的对象, VM也并不是马上对其回收, 因为要真正宣告一个对象死亡, 至少要经历两次标记过程: 第一次是在可达性分析后发现没有与GC Roots相连接的引用链, 第二次是GC对在F-Queue执行队列中的对象进行的小规模标记(对象需要覆盖finalize()方法且没被调用过).


二.垃圾收集算法

2.1 垃圾收集器三种类型串行收集器、并行收集器、并发收集器 。

  1. 串行收集器 
    使用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高。但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器。当然,此收集器也可以用在小数据量(100M 左右)情况下的多处理器机器上。可以使用-XX:+UseSerialGC 打开。
  2. 并行收集器
    1. 对年轻代进行并行垃圾回收,因此可以减少垃圾回收时间。一般在多线程多处理器机器上使用。使用-XX:+UseParallelGC .打开。并行收集器在J2SE5.0第六6更新上引入,在Java SE6.0中进行了增强--可以堆年老代进行并行收集。如果年老代不使用并发收集的话,是使用单线程进行垃圾回收 ,因此会制约扩展能力。使用-XX:+UseParallelOldGC 打开。
    2. 使用-XX:ParallelGCThreads=<N> 设置并行垃圾回收的线程数。此值可以设置与机器处理器数量相等 。
    3. 此收集器可以进行如下配置:
      • 最大垃圾回收暂停: 指定垃圾回收时的最长暂停时间,通过-XX:MaxGCPauseMillis=<N> 指定。<N>为毫秒.如果指定了此值的话,堆大小和垃圾回收相关参数会进行调整以达到指定值 。设定此值可能会减少应用的吞吐量。
      • 吞吐量: 吞吐量为垃圾回收时间与非垃圾回收时间的比值 ,通过-XX:GCTimeRatio=<N> 来设定,公式为1/(1+N) 。例如,-XX:GCTimeRatio=19时,表示5%的时间用于垃圾回收。默认情况为99,即1%的时间用于垃圾回收。
  3. 并发收集器
    可以保证大部分工作都并发进行(应用不停止),垃圾回收只暂停很少的时间,此收集器适合对响应时间要求比较高的中、大规模应用。使用-XX:+UseConcMarkSweepGC 打开。
    1. 并发收集器主要减少年老代的暂停时间,他在应用不停止的情况下使用独立的垃圾回收线程,跟踪可达对象。在每个年老代垃圾回收周期 中,在收集初期并发收集器会对整个应用进行简短的暂停,在收集中还会再暂停一次。第二次暂停会比第一次稍长,在此过程中多个线程同时进行垃圾回收工作。
    2. 并发收集器使用处理器换来短暂的停顿时间 。在一个N个处理器的系统上,并发收集部分使用K/N 个可用处理器进行回收,一般情况下1<=K<=N/4 。
    3. 在只有一个处理器的主机上使用并发收集器 ,设置为incremental mode 模式也可获得较短的停顿时间。
    4. 浮动垃圾 :由于在应用运行的同时进行垃圾回收,所以有些垃圾可能在垃圾回收进行完成时产生,这样就造成了“Floating Garbage”,这些垃圾需要在下次垃圾回收周期时才能回收掉。所以,并发收集器一般需要20% 的预留空间用于这些浮动垃圾。
    5. Concurrent Mode Failure :并发收集器在应用运行时进行收集,所以需要保证堆在垃圾回收的这段时间有足够的空间供程序使用,否则,垃圾回收还未完成,堆空间先满了。这种情况下将会发生“并发模式失败”,此时整个应用将会暂停,进行垃圾回收。
    6. 启动并发收集器 :因为并发收集在应用运行时进行收集,所以必须保证收集完成之前有足够的内存空间供程序使用,否则会出现“Concurrent Mode Failure”。通过设置-XX:CMSInitiatingOccupancyFraction=<N> 指定还有多少剩余堆时开始执行并发收集
  4. 小结
    • 串行处理器: 
      --适用情况:数据量比较小(100M左右);单处理器下并且对响应时间无要求的应用。
      --缺点:只能用于小型应用
    • 并行处理器: 
      --适用情况:“对吞吐量有高要求”,多CPU、对应用响应时间无要求的中、大型应用。举例:后台处理、科学计算。
      --缺点:应用响应时间可能较长
    • 并发处理器:
      --适用情况:“对响应时间有高要求”,多CPU、对应用响应时间有较高要求的中、大型应用。举例:Web服务器/应用服务器、电信交换、集成开发环境。



2.2 垃圾收集器

下面介绍一下HotSpotJDK 7)虚拟机提供的几种垃圾收集器,用户可以根据自己的需求组合出各个年代使用的收集器。

1.Serial&Serial Old

Serial和Serial Old收集器是最基本最古老的收集器,是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程Serial收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿。

2.ParNew

ParNew收集器是Serial收集器的多线程版本,使用多个线程进行垃圾收集。

3.Parallel Scavenge

Parallel Scavenge收集器是一个新生代的多线程收集器(并行收集器)其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量

4.Parallel Old

Parallel OldParallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法

5.CMS

CMSCurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法

6.G1

G1收集器是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型。

最后介绍一下有关收集器设置的JVM常见配置方式:

  1. -XX:+UseSerialGC: //设置串行收集器  
  2. -XX:+UseParallelGC: //设置并行收集器  
  3. -XX:+UseParalledlOldGC: //设置并行年老代收集器  
  4. -XX:+UseConcMarkSweepGC: //设置并发收集器  
  5. //并行收集器设置  
  6. -XX:ParallelGCThreads=n: //设置并行收集器收集时使用的CPU数,并行收集线程数  
  7. -XX:MaxGCPauseMillis=n: //设置并行收集最大暂停时间  
  8. -XX:GCTimeRatio=n: //设置垃圾回收时间占程序运行时间的百分比,公式为1/(1+n)  
  9. //并发收集器设置  
  10. -XX:+CMSIncrementalMode: //设置为增量模式。适用于单CPU情况  
  11. -XX:ParallelGCThreads=n: //设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数  

2.3 整理下新生代和老年代的收集器:

新生代收集器:

Serial (-XX:+UseSerialGC)

ParNew(-XX:+UseParNewGC)

ParallelScavenge(-XX:+UseParallelGC)

G1 收集器



老年代收集器:

SerialOld(-XX:+UseSerialOldGC)

ParallelOld(-XX:+UseParallelOldGC)

CMS(-XX:+UseConcMarkSweepGC)

G1 收集器

 

2.4 JVM小工具

在${JAVA_HOME}/bin/目录下Sun/Oracle给我们提供了一些处理应用程序性能问题、定位故障的工具, 包含

bin描述功能
jps打印Hotspot VM进程VMID、JVM参数、main()函数参数、主类名/Jar路径
jstat查看Hotspot VM 运行时信息类加载、内存、GC[可分代查看]、JIT编译
jinfo查看和修改虚拟机各项配置-flag name=value
jmapheapdump: 生成VM堆转储快照、查询finalize执行队列、Java堆和永久代详细信息jmap -dump:live,format=b,file=heap.bin [VMID]
jstack查看VM当前时刻的线程快照: 当前VM内每一条线程正在执行的方法堆栈集合Thread.getAllStackTraces()提供了类似的功能
javap查看经javac之后产生的JVM字节码代码自动解析.class文件, 避免了去理解class文件格式以及手动解析class文件内容
jcmd一个多功能工具, 可以用来导出堆, 查看Java进程、导出线程信息、 执行GC、查看性能相关数据等几乎集合了jps、jstat、jinfo、jmap、jstack所有功能
jconsole基于JMX的可视化监视、管理工具可以查看内存、线程、类、CPU信息, 以及对JMX MBean进行管理
jvisualvmJDK中最强大运行监视和故障处理工具可以监控内存泄露、跟踪垃圾回收、执行时内存分析、CPU分析、线程分析…

VM常用参数整理

参数描述
-Xms最小堆大小
-Xmx最大堆大小
-Xmn新生代大小
-XX:PermSize永久代大小
-XX:MaxPermSize永久代最大大小
-XX:+PrintGC输出GC日志
-verbose:gc-
-XX:+PrintGCDetails输出GC的详细日志
-XX:+PrintGCTimeStamps输出GC时间戳(以基准时间的形式)
-XX:+PrintHeapAtGC在进行GC的前后打印出堆的信息
-Xloggc:/path/gc.log日志文件的输出路径
-XX:+PrintGCApplicationStoppedTime打印由GC产生的停顿时间


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值