一.概述 

  • 哪些内存需要回收?
  • 什么时候回收?
  • 如何回收?

二.对象已死吗 

1.引用计数算法 

  1. 定义:给对象添加一个引用计数器,当增加一个引用时,加1,当一个引用时,减1;

  2. 缺陷:当对象之间互相循环引用时,就会变的像“不死对象”;

2.可达性分析算法

  在主流的商用程序语言(Java、C#,甚至包括前面提到的古老的Lisp)的主流实现中, 都是称通过可达性分析(Reachability Analysis)来判定对象是否存活的。这个算法的基本思 路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所 走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连 (用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。如 图3-1所示,对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达 的,所以它们将会被判定为是可回收的对象

在Java语言中,可作为GC Roots的对象包括下面几种:

虚拟机栈(栈帧中的本地变量表)中引用的对象。

方法区中类静态属性引用的对象。

方法区中常量引用的对象。

本地方法栈中JNI(即一般说的Native方法)引用的对象。

3、引用

  • 强引用:“=”实现,引用只要还在,就不会被GC回收;
  • 软引用:SoftReference实现,在内存不足发生OOM之期,就回收掉该引用;
  • 弱引用:WeakReference实现,在下一次GC前,就回收掉该引用;
  • 虚引用:PhantomReference实现,在任何时候可能被回收,不过回收后可以收到系统的通知;

4.生存还是死亡 (finalize方法自救)

  • 如果GC Roots 不可达,进行第一次标记;
  • 再看finalize()方法有没有被复写,有则先执行finalize()方法;
  1. 逃命方法:将自己关联到类变量之类或者某对象的成员变量的;
  2. 终身只有一次调用机会;
  • 接着GC进行第二次标记,如果没有逃脱,则回收;

5.无用的类

  • 所有该类的实例已被回收
  • 该类的ClassLoad已被回收
  • 该类对应的java.lang.Class没有在任何地方被引用,不存在该类的反射

三.垃圾回收算法

1、标记——清除法

  • 方案:先标记,然后直接回收
  • 缺陷:产生大量碎片,不好分配大内存

2、复制算法

  • 方案:将内存分为AB两块,回收时,将A块的对象全部复制到B,然后把未回收的上移,然后把已使用过的A全部清除;
  • 优点:实现简单,运行高效;
  • 缺陷:有一半处于无用状态,浪费;
  • HotSpot:通过 Eden:Surivor:Surivor=8:1:1的比例分配,这样只有10%的空间浪费;不足时,需要依赖其他内存分配担保;

3、标记—整理算法

  • 方案:标记—清理之后,再整体上移;
  • 适应:适合老年代内存区使用

4、分代收集算法

  • 新生代:使用复制算法
  • 老年代:使用“标记-清理”或者“标记—整理”算法

四.垃圾收集器

1、 Serial收集器

  • 这个收集器是一个单线程收集器,
  • 只会使用一个CPU或者一条收集线程进行垃圾收集工作
  • 其余的工作现场必须暂停,直到收集结束

2、ParNew收集器

  • Serial收集器的多线程版本
  • 垃圾收集器线程和工作线程同时工作

3、Paraller Scavenge收集器

  • 目标:达到一个可控的吞吐量
  • 吞吐量: 用户运行时间/(用户运行时间+垃圾回收时间)
  • GC自适应调节:调整参数提供最合适的停顿时间或者最大的吞吐量

4、CMS收集器

  • 目标:最短回收停顿时间
  • 步骤:
  1. 初始标记
  2. 并发标记
  3. 重新标记
  4. 并发清除
  • 缺点:
  1. 对CPU资源非常敏感
  2. 无法处理浮动垃圾
  3. 基于“标记-清除”算法实现,碎片多

5、G1 收集器

  • 并行与并发
  • 分代收集
  • 空间整合:
  1. 整体看:基于“标记-整理”算法
  2. 局部看:基于“复制”算法
  • 可预测停顿
  1. 有计划避免 Java 堆中进行全区域的垃圾收集

6、GC日志

33.125: [GC [DefNew: 3324k ->152k(3712k),0.0025925 secs] 3324k->152k(11904k),0.0031680 secs]
  • 33.125: GC发生时间
  • [GC:GC停顿类型,如果是 [Full GC
  • [DefNew: 垃圾回收器类型
  • 3324k ->152k(3712k): GC前内存区域已使用容量-> GC后内存区域已使用容量(内存区域总容量)
  • 3324k->152k(11904k): GC前Java堆已使用容量->GC后Java堆已使用容量
  • 0.0025925:内存区域GC所占用时间

五.内存分配和回收策略

最终都是给对象分配内存和回收分配给对象的内存

  • 对象优先在 Eden 分配
  • 大对象直接进入老年代
  • 长期存活的对象进入老年代
  • 动态对象年龄判定

如果在一个 Survivor 空间中相同年龄所占内存大小占有一半,那么大于或者等于该年龄的对象直接进入老年代

  • 空间分配担保

新生代的回收采用“复制算法”,如果没有足够的内存空间,需要老生代来担保,将一部分对象直接进入老年代,如果老年代空间还是不足,就有危险了。所以就根据以前进入老年代的对象容量大小的平均值来做个参考。通过 Fulll GC 对老年代进行一次GC,尽量腾出更多的空间。以防担保失败。

  • Minor Gc 和 Full GC
  1. Minor Gc:新生代的GC,很快
  2. Full GC:老年代的GC,慢10倍

六.小结

  本篇了解引用的算法,由此去判断一个对象是"死”还是“活”,四种引用类型,由强至弱,生存能力越来越差,被 GC 回收的可能性也就越高。当然在一生中有唯一一次的自救机会,就是复写 finalize() 方法。进行垃圾回收时,会影响到性能。所以,出了各种回收算法以及垃圾回收器。这些各有优劣,只有适合当前环境的才是最好的。

深入理解Java虚拟机03--垃圾收集器与内存分配策略的更多相关文章

  1. 深入理解Java虚拟机:垃圾收集器与内存分配策略

    目录 3.2 对象已死吗 判断一个对象是否可被回收 引用类型 finalize() 回收方法区 3.3. 垃圾收集算法 1.Mark-Sweep(标记-清除)算法 2.Copying(复制)算法 3. ...

  2. 《深入理解Java虚拟机》——垃圾收集器与内存分配策略

    GC需要完成: 哪些内存需要回收 什么时候回收 如何回收 如何确定对象不再使用 引用计数算法 给对象添加一个引用计数器,当有一个地方引用它时,计数器值进行加1操作:当引用失效时,计数器值进行减1操作: ...

  3. 深入理解Java虚拟机笔记——垃圾收集器与内存分配策略

    目录 判断对象是否死亡 引用计数器算法 可达性分析算法 各种引用 回收方法区 垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 HotSpot算法实现 枚举根节点 GC停顿(Sto ...

  4. 深入理解java虚拟机(3)垃圾收集器与内存分配策略

    一.根搜索算法: (1)定义:通过一系列名为"GC Roots"的对象作为起点,从这些起点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连的时 ...

  5. 深入JAVA虚拟机笔记-垃圾收集器与内存分配策略

    第三章:垃圾收集器与内存分配 问题:1.哪些内存需要回收 2.什么时候回收 3.怎么回收 回收方法区:

  6. java虚拟机(六)--垃圾收集器和内存分配策略

    目前没有完美的收集器,不同的厂商.版本的虚拟机提供的垃圾收集器会有很大的差别,用户根据自己应用特点和要求组合出各个年代所使用 的收集器.基于jdk1.7Update14之后的虚拟机. HotSpot的 ...

  7. 深入理解Java虚拟机之读书笔记三 内存分配策略

    一般的内存分配是指堆上的分配,但也可能经过JIT编译后被拆散为标量类型并间接地在栈上分配.对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配,少数情况下直接分 ...

  8. 深入理解java虚拟机----->垃圾收集器与内存分配策略(下)

    1.  前言 内存分配与回收策略 JVM堆的结构分析(新生代.老年代.永久代) 对象优先在Eden分配 大对象直接进入老年代 长期存活的对象将进入老年代 动态对象年龄判定 空间分配担保  2.  垃圾 ...

  9. 《深入理解Java虚拟机》(三)垃圾收集器与内存分配策略

    垃圾收集器与内存分配策略 详解 3.1 概述 本文参考的是周志明的 <深入理解Java虚拟机>第三章 ,为了整理思路,简单记录一下,方便后期查阅. 3.2 对象已死吗 在垃圾收集器进行回收 ...

  10. 《深入理解java虚拟机》第三章 垃圾收集器与内存分配策略

    第三章 垃圾收集器与内存分配策略 3.1 概述 哪些内存需要回收 何时回收 如何回收 程序计数器.虚拟机栈.本地方法栈3个区域随线程而生灭. java堆和方法区的内存需要回收.   3.2 对象已死吗 ...

随机推荐

  1. 安卓视频播放器(VideoView)

    VideoView是安卓自带的视频播放器类,该类集成有显示和控制两大部分,在布局文件中添加VideoView然后在java文件中简单的调用控制命令,即可实现本地或者网络视频的播放.本章实现视频的居中播 ...

  2. MySQL基础整理(一)之SQL基础(未完成)

    大家好,我是浅墨竹染,以下是MySQL基础整理(一)之SQL基础 1.SQL简介 SQL(Structure Query Language)是一种结构化查询语言,是使用关系模型的数据库应用语言. 2. ...

  3. ModelState 错误信息输出

    在MVC的项目中,我们通常情况下,为了方便(偷懒),会直接使用 !ModelState.IsValid 来判断实体的验证是否正确,但是这样对于用户的体验是不好的,当填写的内容比较多的时候,用户需要自己 ...

  4. 实现quartz定时器及quartz定时器原理介绍

    今天研究定时器,在网上看了一篇不错的文章,推荐给大家! 实现quartz定时器及quartz定时器原理介绍

  5. Apache-Flink深度解析-TableAPI

    您可能感兴趣的文章合集: Flink入门 Flink DataSet&DataSteam API Flink集群部署 Flink重启策略 Flink分布式缓存 Flink重启策略 Flink中 ...

  6. LINUX LVM和快照卷配置和管理

    具体参考这个文章把: http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_linux_042_lvm.html 1.LVM是什么 逻辑卷管理LVM是一个多 ...

  7. Java 并发编程-再谈 AbstractQueuedSynchronizer 2:共享模式与基于 Condition 的等待 / 通知机制实现

    共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchroni ...

  8. 项目实战1—LNMP的搭建、nginx的ssl加密、身份验证的实现

    总项目流程图,详见 http://www.cnblogs.com/along21/p/8000812.html 实战一:搭建lnmp及类小米等商业网站的实现 环境:关闭防火墙,selinux 1.安装 ...

  9. 一篇文章详解python的字符编码问题

    一:什么是编码 将明文转换为计算机可以识别的编码文本称为“编码”.反之从计算机可识别的编码文本转回为明文为“解码”. 那么什么是明文呢,首先我们从一段信息说起,消息以人们可以理解,易懂的表示存在,我们 ...

  10. MyBatis源码解析(十一)——Parsing解析模块之通用标记解析器(GenericTokenParser)与标记处理器(TokenHandler)

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6724223.html 1.回顾 上面的几篇解析了类型模块,在MyBatis中类型模块包含的 ...