1、对象已死?
a、引用计数算法:缺点是它很难解决对象之间的相互循环引用的问题,Java语言中没有选用它。
b、根搜索算法(GC Roots Tracing):通过一系列的名为“GC Roots”的对象作为起始点,开始向下搜索,走过的路径称为引用链,当一个对象没有任何引用链相连,表面此对象不可达。在Java语言中,可作为GC Roots的对象包括:
虚拟机栈(栈帧中的本地变量表)中的引用的对象。
方法区中的类静态属性引用的对象。
方法区中的常量引用的对象。
本地方法栈中JNI的引用的对象。
c、再谈引用:Java把引用分成强引用,软引用,弱引用和虚引用。由强到弱。
强引用:只要强应用在存在,垃圾收集器永远不会回收掉被引用的对象。
软引用:在系统将要发生内存溢出异常之前,把对象列进回收范围之中并进行第二次回收。如果这次回收之后还是没有足够的内存,才会抛出内存溢出异常。SoftReference
弱引用:被弱引用关联的对象只能生存到下一次垃圾回收发生之前。WeakReference
虚引用:一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。唯一目的是:对象被回收时收到一个系统通知。PhantomReference
d、生存还是死亡?
对象不可达之后,进入“缓刑”阶段。第一次根搜索后,不可达对象有两种情况:一是直接回收,二是放入F-Queue队列。放入F-Queue队列的条件是覆盖了finalize()方法且没有被调用过。总结一下就是:对象可以通过覆盖finalize()方法在被GC时拯救自己一次。注意:任何一个对象的finalize()方法都只会被系统自动调用一次。
e、回收方法区
方法区的回收主要集中在:废弃常量和无用的类。废弃常量的回收与Java堆对象的回收类似,无用类的回收需要满足3个条件:而且只是可以回收,通过参数控制。
该类的所有实例都已经被回收
加载该类的ClassLoader已经被回收
该类对应的Class对象没有在任何地方被引用。
在大量使用反射、动态代理、CGLib等bytecode框架的场景,以及动态生成JSP和OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能。
2、垃圾收集算法
a、标记-清除算法:分成标记和清除两个阶段。首先标记出所有需要回收的对象,标记完成后统一回收掉所有被标记的对象。
有点:实现简单,逻辑直接
缺点两个:效率比较低,空间不连续,大量碎片。
b、复制算法:为了解决效率问题。平分内存成两块,每次只用一块,快用完时,复制替换。
优点:实现简单,运行高效
缺点两个:可用内存是原来的一半;当对象存活率较高时,复制带来低效率。
HotSpot虚拟机吻合了IBM的研究,改进了该算法,分成了一个较大的Eden区和两个较小的Survivor区。效率更好,但需要担保内存。比较符合新生代使用。
c、标记-整理算法:不直接清理可回收对象,让所有存活的对象向一端移动,然后清理掉边界以外的内存。比较适合于老年代使用。
d、分代收集算法:根据对象的存活周期不同将内存划分为几块。根据各个年代的特点采用最合适的收集算法。新生代一般使用复制算法,老年代采用标记-清除算法或者标记-整理算法。
3、垃圾收集器
上图展示了7种作用于不同分代的收集器,连线表示收集器之间可以搭配使用。
a、Serial收集器:
它是一个单线程的收集器,只会使用一个CPU和一条收集线程去完成垃圾收集工作。同时,它也是串行收集器:在进行垃圾收集时,必须暂停其他所有的工作线程(Stop The World),直到它收集结束。在用户不可见的情况下,把用户的正常工作线程全部停掉。
这个简单而高效(特别是单个CPU的环境)的收集器适合于运行在Client模式下的虚拟机。
b、ParNew收集器
是Serial收集器的多线程版本,与Serial收集器唯一的区别就在于使用了多条线程进行收集。
目前只有Serial和ParNew能与CMS收集器配合工作。CMS是JDK1.5中引入的第一款并发收集器:垃圾收集线程与用户线程可同时工作。ParNew在多CPU的情况下才具备性能优势。
c、Parallel Scavenge收集器
是一个新生代收集器,使用复制算法,并行多线程收集器。它的特点是关注于达到一个可控制的吞吐量,最大地利用CUP的时间。同时,Parallel Scavenge收集器通过一个开关参数还可以开启自适应调节策略。
d、Serial Old收集器
它是Serial收集器的老年代版本,单线程,标记-整理算法。主要用于Client模式下。同时:可以Parallel Scavenge收集器搭配使用,作为CMS收集器的后背预案。
e、Parallel Old收集器
它是Parallel Scavenge收集器的老年代版本,多线程和标记-整理算法。与Paralle Scavenge一起打造吞吐量优先的组合。在注重吞吐量及CPU资源敏感的场合,考虑使用。
f、CMS收集器(Concurrent Mark Sweep)
以获取最短回收停顿时间为目标,适合于注重服务的相应速度的场合。基于标记-清除算法。整个过程四个步骤:
初始标记(CMS initial mark)
并发标记(CMS concurrent mark)
重新标记(CMS remark)
并发清除(CMS concurrent sweep)
注意:初始标记和重新标记一样有Stop The World。初始标记只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行Roots Tracing的过程,而重新标记则是为了修正并发标记期间,因用户程序运作而导致标记发生变动的那一部分对象的标记记录,停顿时间不长。耗时较长的并发标记和并发清除过程,收集线程和用户线程可一起工作。
缺点:
对CPU资源非常敏感。默认启动线程数:(CPU数量+3)/4。
无法处理浮动垃圾,可能出现Concurrent Mode Failure失败导致一次Full GC。CMS运行期间预留的内存无法满足程序的需要,出现Concurrent Mode Failure失败。虚拟机启动后备预案,临时使用Serial Old收集器重新老年代的垃圾收集。
使用的标记-清除算法导致大量内存碎片。可能导致提前Full GC。使用参数可控制Full GC发生后附带的空间碎片整理频率。
g、G1收集器
与CMS相比有两个改进:基于标记-整理算法,消除了内存碎片问题;精确地控制停顿时长。G1将整个Java堆分成多个大小固定的独立区域,跟踪区域垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先收集垃圾最多的区域。
4、垃圾收集器参数总结
深入理解Java虚拟机之读书笔记二 垃圾收集器的更多相关文章
-
《深入理解 Java 虚拟机》读书笔记:垃圾收集器与内存分配策略
正文 垃圾收集器关注的是 Java 堆和方法区,因为这部分内存的分配和回收是动态的.只有在程序处于运行期间时才能知道会创建哪些对象,也才能知道需要多少内存. 虚拟机栈和本地方法栈则不需要过多考虑回收的 ...
-
《深入理解Java虚拟机》读书笔记:垃圾收集器与内存分配策略
请移步至:http://zhanjindong.info/2014/05/18/java-gc/
-
《深入java虚拟机》读书笔记之垃圾收集器与内存分配策略
前言 该读书笔记用于记录在学习<深入理解Java虚拟机--JVM高级特性与最佳实践>一书中的一些重要知识点,对其中的部分内容进行归纳,或者是对其中不明白的地方做一些注释.主要是方便之后进行 ...
-
《深入理解java虚拟机》读书笔记二——第三章
第三章 垃圾收集器与内存分配策略 1.判断对象是否已死 引用计数法: 给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,每当引用失效时,计数器值就减1. 任何时刻计数器为0的对象就是不 ...
-
《深入理解Java虚拟机》读书笔记二
第三章 垃圾收集器与内存分配策略 1.判断对象是否已死 引用计数法: 给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,每当引用失效时,计数器值就减1. 任何时刻计数器为0的对象就是不 ...
-
《深入理解java虚拟机》学习笔记四/垃圾收集器GC学习/一
Grabage Collection GC GC要完毕的三件事情: 哪些内存须要回收? 什么时候回收? 怎样回收? 内存运行时区域的各个部分中: 程序计数器.虚拟机栈.本地方法栈这3个区域随 ...
-
《深入理解 Java 虚拟机》读书笔记:Java 内存区域与内存溢出异常
前言 最近开始看这本书,记得前段时间拿起这本书的时候,心情是相当沉重的!当时的剧本是这样的-- 内景.家里 - 下午 我(画外):唉,有点无聊啊!(偶然撇过书架)这么多书得看到什么时候啊,要不要拿一本 ...
-
《深入理解Java虚拟机》(三)垃圾收集器与内存分配策略
垃圾收集器与内存分配策略 详解 3.1 概述 本文参考的是周志明的 <深入理解Java虚拟机>第三章 ,为了整理思路,简单记录一下,方便后期查阅. 3.2 对象已死吗 在垃圾收集器进行回收 ...
-
《深入理解java虚拟机》第三章 垃圾收集器与内存分配策略
第三章 垃圾收集器与内存分配策略 3.1 概述 哪些内存需要回收 何时回收 如何回收 程序计数器.虚拟机栈.本地方法栈3个区域随线程而生灭. java堆和方法区的内存需要回收. 3.2 对象已死吗 ...
随机推荐
-
Android N开发 你需要知道的一切
title: Android N开发 你需要知道的一切 tags: Android N,Android7.0,Android --- 转载请注明出处:http://www.cnblogs.com/yi ...
-
关于js中的this之判断this
this绑定规则的优先级顺序 new操作符绑定 > 显示绑定 > 隐式绑定 > 默认绑定 所以在判断函数在某个调用位置应用的是哪条规则,可以按下列这样的顺序 if(函数在ne ...
-
CA02检验计划批量导入 模板在文件
*&---------------------------------------------------------------------* *& PROGRAM NAME(EN) ...
-
PHP 基础笔记
数据类型 字符串 整数 浮点数 布尔值 数组 对象 NULL 未定义的变量,数据类型为 NULL. PHP 中数组和对象是不同的类型,而 js 中数组即为对象.(ps: es6 已经内置了 class ...
-
【maven】 maven的setting.xml文件的详解
1 Maven的安装 安装Maven之前要确保已经安装好了jdk,并且配置好了环境变量JAVA_HOME.具体安装步骤如下: 从apache网上下载maven项目的压缩包.下载地址为:ht ...
-
Chrome plug-in 和Extension
"扩展"和"插件",其实都是软件组件的一种形式,Chrome 只不过是把两种类型的组件分别给与了专有名称,一个叫"扩展",另一个叫" ...
-
javascript 变量的作用范围
来自: http://hanxin0311.iteye.com/blog/181127 1.根据作用范围不同,变量有全局变量和局部变量两种.在函数里定义的变量为局部变量,局部变量只在函数内有效. 如果 ...
-
WS之cxf与spring整合2
在action中加入webservice
-
javascript模块化编程(转载)
Javascript 模块化编程 作者: 阮一峰 发布时间: 2013-01-08 18:04 阅读: 7632 次 推荐: 40 原文链接 [收藏] 随着网站逐渐变成"互 ...
-
python中线程和进程(二)
目录 线程同步 Event Lock RLock Condition Barrier semaphore GIL 线程同步 线程同步,即线程之间协同工作,一个线程访问某些数据时,其他线程不能访问这些数 ...