java与C++之间有一道动态内存分配和垃圾收集的“墙”,墙里面的人想出来,墙外边的人想进去,或许只有骑在墙上才能清楚的了解,墙内墙外都是牢笼。
上面一句出自《深入理解java虚拟机》,我做了适当的修改,因为之前是C++出身,虽然C++具有高效 ,快速等特点,威力也大,但C++的内存手动分配和手动回收也令人懊恼,所以一般事物威力越大的同时爆发起的脾气也是越大,所以语言没有好坏之分,只是针对的功能和应用不同。这里只是做了一个简单的对比,C++和java都是优秀的编程语言,各自应用的场景和解决的问题不同,没有最好的语言,只有最合适的语言(针对某一特定的场景和问题)。这里做了一个对比,只是想突出java的自动内存管理,但如题所说,都是牢笼。
Java中的内存管理主要依赖一个叫垃圾收集器的东西,这东西就像一个保姆一样,负责回收虚拟机中产生的废弃对象即垃圾。那什么是垃圾呢?原理上来讲垃圾即虚拟机内存中不在被使用的对象,那怎么判断一个对象是不是一个垃圾呢?原理上有两种方法来判断,一种是计数器方式,另一种是可达性分析,通俗来讲计数器方式:就是在对象中设置一个引用计数器,每当别的对象引用一次该对象,就把计数器加1,不在引用时减1。当引用计数器为0时则判断这个对象为垃圾。可达性分析法:维护了一个对象引用树,在判断垃圾时,从GC根节点开始遍历,如果一个对象不在这个可达性树中,则这个对象为垃圾,如下图1所示,F不在可达性引用树中,从GCRoot在可达性分析树路径遍历不到该对象,说明F是一个垃圾。但是现在虚拟机一般使用可达性分析来进行判断一个对象是否是垃圾,这是为什么呢?为什么不使用引用计数器法?下面看这种情况,假设G、H都是垃圾,如下图2,G对象引用了H对象,H对象引用了G对象,这样GH形成了相互引用,但是G、H本身又是垃圾,按照引用计数法,计数器不为零,不能判定为是垃圾,所以垃圾无法被回收,造成内存泄漏。
明白了哪些是垃圾,下面就要进行了垃圾回收,JVM实现内存自动管理依赖的是垃圾回收器。在正式介绍JVM垃圾收集器之前,我们先了解一下垃圾收集器的设计思想。明白了垃圾收集器设计的思想,有助于更好的理解JVM中各种垃圾收集器。
垃圾收集器的设计思想一共有三种,复制算法,标记清除算法,标记整理算法,分代收集算法。下面详细介绍每种算法。
复制算法很简单,简单来讲,将内存区域划分为两块,每次只用其中的一块。如图3所示,当发生垃圾收集时,将左边存活的对象复制到右边内存中,然后将左边的清空,反复轮换。
标记清除算法,就想将内存中的垃圾先进行标记,然后进行清除。如下图4所示。
标记整理算法与标记清除算法相似,只不过比标记清除算法多了一步内存整理,算法思想为:首先进行垃圾标记,然后进行垃圾清除,最后将存活的对象向内存的一边进行移动,使其内存规整,整个过程如下图5所示。
分代收集算法主要是根据虚拟机中内存区域的划分,在不同的内存区域使用不同的垃圾收集器。
上面介绍了不同的垃圾收集算法,但是不同的垃圾收集算法有什么特点呢?或者说不同的垃圾收集器存在什么问题。下面对此问题做一个总结。
|
垃圾收算法 |
特点 |
缺点 |
使用场景 |
|
复制算法 |
实现简单,运行高效,内存分配不用担心内存碎片 |
1.内存缩小为原来的一半。 2.如果存活对象较多,那么要进行较多复制,效率会变低。 |
新生代,适用于“朝生夕死”的对象垃圾收集。 |
|
标记整理 |
不会产生内存碎片 |
要对垃圾进行标记,清除,对存活的对象进行整理,效率相对较低。 |
适用于老年代垃圾收集 |
|
标记清除 |
--- |
1.要经过标记和清理,效率较低。 2.会产生内存碎片。 |
用在获取最短垃圾收集停顿时间的收集器 |
|
分代收集 |
根据不同的内存区域,结合了标记清除,标记整理,复制算法的有点。 |
-------------- |
不同的内存区域使用相应的垃圾收集器 |
了解了上面的一般垃圾收集器收集算法,下面看看具体实现上述算法的收集器。为了有一个直观的概念,先看一个jvm中总的垃圾收集器图。下面通过一张表详细介绍每一种垃圾收集器。
|
垃圾收集器 |
使用算法 |
特点 |
使用场景 |
|
Serial |
复制算法 |
单线程,必须停掉所有用户线程,进行垃圾收集 |
Client模式下,新生代收集器 |
|
ParNew |
复制算法 |
多线程垃圾收集器,必须停掉所有用户线程进行垃圾收集。 |
运行在Server模式下的新生代收集器 |
|
ParallelScavenge |
复制算法 |
多线程吞吐量优先收集器,能达到一个可控制的吞吐量,具有自适应GC调解策略, |
关注吞吐量的时候使用该收集器 |
|
Serial Old |
标记整理 |
单线程 |
Client模式下老年代收集器 |
|
CMS |
标记清除 |
并发最短停顿时间收集器; 对CPU敏感,无法处理浮动垃圾,产生内存碎片 |
用在互联网或服务器中的收集器,系统停顿时间最短,用户体验好。 |
|
G1收集器 |
分代收集 |
并行与并发;分代收集;空间整合,不会产生内存suip;可预测停顿时间。 |
面向服务端应用的垃圾收集器 |
以上就是java整个垃圾回收相关的内容。