在上一章中,咱们了解到程序计数器、虚拟机栈、本地方法栈等线程私有的区域的生命周期都是跟随线程的生命周期的变化而变化的,而java堆和方法区等线程共享的区域的生命周期咱们就没有介绍了。html
所以,本章的主要内容就是介绍java堆和方法区等线程共享的区域上管理,即java堆和方法区上GC。咱们将从如下几个方面进行展开:java
要特别注意,本章节主要讨论的是java堆和方法区上的GC。web
要想了解GC,首先要了解什么是垃圾对象,或者说是什么样的对象才符合垃圾回收的原则?所谓的垃圾就是在jvm中用不到的内存区域,由于内存资源老是有限的,用不到的内存必定要从新被操做系统收集整理后再次使用。因此,垃圾回收的本质就是对内存空间的从新整理,把符合特定条件的内存区域从新回收,以供操做系统后期再次使用。算法
而线程私有的内存空间由线程本身管理,那线程共享的区域的管理就须要额外的功能模块来管理了,这个额外的功能模块就是垃圾回收器,又由于线程共享的区域上存储的主要内容是java的类对象和方法。所以咱们就要研究什么样的对象才可以被回收。浏览器
研究对象是否被回收,只须要研究对象是否被使用便可。换句话来讲,就是研究对象是否被引用。目前来讲,判断对象是否被引用有两种方式:安全
引用计数法:为每个对象都建立一个引用计数的属性,若是有其余对象引用这个对象,就为这个对象的引用计数的属性加一,引用释放时计数就减一,计数为0的时候就能够被回收了。这种方式没法解决对象之间相互引用的问题。固然java中也不会使用这种方式来判断对象是否存活了。服务器
可达性分析法:引入GCroot概念,若是在GCroot和一个对象之间没有可达路径,那么对象就是不可达的。要注意的是:不可达对象不等价于可回收对象,不可达对象变成回收对象至少要通过两次标记过程,两次标记以后仍然是可回收对象,那将面临回收。多线程
在Java语言中,GC Roots包括:并发
TODO: 可达性分析法的具体实现过程oracle
因为java虚拟机规范中,没有要求虚拟机在方法区实现垃圾收集,所以方法区的垃圾收集是根据具体的虚拟机实现来肯定的。在HotSpot中,方法区就是永久区。永久区的垃圾回收对象是废弃常量和无用的类。
判断一个类是否无用比较苛刻,要同时知足如下3个方面的条件:
垃圾回收由两部分组成,一部分是GC算法,另外一部分是实现GC算法的回收器。
本小节主要研究垃圾回收算法的种类、具体实现原理、适用对象、优缺点等内容。
标记-整理算法
复制算法
标记-清除算法
分代回收算法
在早起的jdk版本中,咱们关注的是清理jvm中全部的垃圾,所以产生了单线程的Serial收集器和Serial Old收集器,这保证了清理时的稳定性与高效性,但这样一样会带来一下问题,如因为清理线程独占系统资源形成用户程序线程暂停而引发全局停顿的问题;后来,咱们开始关注系统的吞吐量(即用户应用程序运行时间与总运行时间的比值,吞吐量从某种意义上也体现了全局停顿时间的概念),咱们认为要提升系统的吞吐量,所以产生了Parallel Scavenge收集器和Parallel Old收集器;再后来,咱们把关注点转移到减小全局停顿时间上,所以产生了跨时代的CMS收集器。
此外,因为在垃圾收集过程当中,会产生全局停顿的现象,这就引出咱们评判一个垃圾收集器性能好坏的评判标准:咱们在评判一个垃圾收集器性能好坏时,本质上讲,咱们是在讨论这个垃圾收集器在收集垃圾时所产生的全局停顿时间的长短,即全局停顿时间越短,垃圾收集器的性能越好
。可是这句话不是绝对的,咱们只是提供了一种观察垃圾收集器性能好坏的方法。
下面的内容,咱们是从分代的角度去讲述垃圾收集器的种类,固然读者也能够从垃圾收集器的发展阶段中的关注点来划分。本小节中也将主要讲解各类回收器的种类、适用范围、实现原理、优缺点、参数控制等内容。
上面的图很是重要! 说明: 若是两个收集器之间存在连线说明他们之间能够搭配使用。
Serial收集器
-XX:+UseSerialGC
参数控制ParNew收集器
-XX:ParallelGCThreads
参数来限制垃圾收集器的线程数Parallel Scavenge收集器
-XX:MaxGCPauseMillis
参数来控制最大垃圾收集停顿时间-XX:GCTimeRatio
参数来直接设置吞吐量大小-XX:+UseAdaptiveSizePolicy
参数来开启GC自适应的调节策略
,这个也是与Par New收集器的重要区别三个新生代收集器所采用的收集算法都是复制算法,而且它们的功能也是逐步完善的。ParNew收集器在Serial收集器的基础上面加上了多线程的功能,Parallel Scavenge收集器又在ParNew收集器的基础上加了控制吞吐量的控制功能。
Serial Old收集器
Parallel Old收集器
:star: CMS收集器
-XX:+CMSFullGCsBeforeCompaction
参数设置执行多少次不压缩FullGC后,跟着来一次带压缩的。如:这个参数的值为2,就是在执行2次不压缩的FullGC以后,紧接着会再执行1次压缩的FullGC)等G1收集器(又称:Garbage—First)是目前技术发展的最前沿成果之一,它既能够做用到新生代又能够做用到老年代,所以它也被称为通用收集器。
相对于CMS垃圾收集器,它具备如下特色:
使用范围
G1收集器的几个重要内容
G1堆分配
-XX:G1HeapRegionSize
参数(该参数的默认值并非必定的,它是根据java堆初始化时大小决定的,取值范围为:1M到32M,且要是2的指数)来设置。新生代GC
老年代GC
GC的停顿主要来源于可达性分析上,程序执行时并不是在全部地方都能停顿下来开始GC,只有在到达安全点时才能暂停。
安全点的选定基本上是以程序“是否具备让程序长时间执行的特征”为标准进行选定的——由于每条指令执行的时间都很是短暂,程序不太可能由于指令流长度太长这个缘由而过长时间运行,“长时间执行”的最明显特征就是指令序列复用,例如方法调用、循环跳转、异常跳转等,因此具备这些功能的指令才会产生安全点。
接下来的问题就在于,如何让程序在须要GC时都跑到安全点上停顿下来,大多数JVM的实现都是采用主动式中断的思想。
主动式中断的思想是当GC须要中断线程的时候,不直接对线程操做,仅仅简单地设置一个标志,各个线程执行时主动去轮询这个标志,发现中断标志为真时就本身中断挂起,轮询标志的地方和安全点是重合的,另外再加上建立对象须要分配内存的地方。
// TODO
Serial收集器和SerialOld收集器
ParNew收集器与SerialOld收集器
Parallel Scavenge收集器和Parallel Old收集器
G1收集器
MinorGC日志格式
FullGC日志格式
调优工具分为两类,一类是jdk自带的,一类是第三方的。
jps:JVM Process Status Tool,显示指定系统内全部的HotSpot虚拟机进程。
jstat:JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它能够显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
jmap:JVM Memory Map命令用于生成heap dump文件
jhat:JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,能够在浏览器中查看
jstack:用于生成java虚拟机当前时刻的线程快照。
jinfo:JVM Configuration info 这个命令做用是实时查看和调整虚拟机运行参数。
jconsole:Java Monitoring and Management Console是从java5开始,在JDK中自带的java监控和管理控制台,用于对JVM中内存,线程和类等的监控
jvisualvm:jdk自带全能工具,能够分析内存快照、线程快照;监控内存变化、GC变化等。
MAT,Memory Analyzer Tool,一个基于Eclipse的内存分析工具,是一个快速、功能丰富的Java heap分析工具,它能够帮助咱们查找内存泄漏和减小内存消耗
GChisto:一款专业分析gc日志的工具
// TODO
[0] : Jvm 系列(三):GC 算法 垃圾收集器
[1] : Java虚拟机(JVM)你只要看这一篇就够了!
[2] : JVM看这一篇就够了
[3] : JAVA核心知识点整理
[4] : 《深刻理解Java虚拟机——JVM高级特性与最佳实践》
[5] : Java Hotspot G1 GC的一些关键技术
[6] : Getting Started with the G1 Garbage Collector
[7] :JVM GC参数以及GC算法的应用