最近想好好复习一下java虚拟机,我想通过深读 【理解Java虚拟机 jvm 高级特性与最佳实践】 (作者 周志明) 并且通过写一些博客总结来将该书读薄读透,这里文章内容仅仅是个人阅读后简短总结,加强学习深度的同时方便进行知识的回顾之用。如涉及版权还望周大神看到后告知一下小弟,我会第一时间将文章下线,在此强烈推荐大家买纸质图书 【理解Java虚拟机 jvm 高级特性与最佳实践】 (作者 周志明) 进行阅读,学习java虚拟机必备。努力学习只为遇到更好的你!

第三章 垃圾收集器与内存分配策略

Java 与 C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面 的人却想出来

1 垃圾收集三个疑问

说起垃圾收集我们必须明确三件事情:
1 那些内存需要回收? 2 如何回收? 3 什么时候回收? 将这三个问题搞清楚 你就会对真正的理解垃圾收集是个什么东东?我这里将围绕这三个问题进行阐述。带着疑问去学习。

1 那些内存需要回收?

关于第二个问题和第三个问题会在后面阐述到,我们来说一下 那些内存需要进行回收。
java虚拟机的 程序计数器虚拟机栈本地方法栈
这三个内存区域 生命周期和线程一致,Sun HotSopt 直接将本地方法栈和Java 虚拟机栈 合二为一 我们这将虚拟机栈 和本地方法栈 统称为栈。而栈中存储的就是栈帧。我们的方法执行就是执行入栈和出栈的操作。在编译期每个栈帧占用内存大小已经是确定了,而程序计数器占用的内存是比较小的,所以我们不用太担心这三个内存区域的回收问题,因为一旦方法结束或线程结束内存就自然跟着回收了。
垃圾收集需要关注的是Java堆方法区,因为这2块内存区域内存非配和回收是不确定的,它们在运行期间才会知道要创建多少对象。需要转载多少类。还有就是每个对象存活的时间也各不一样。我们需要通过不同的策略区进行内存的分配和回收。

2 如何回收?

我们将不可能在被任何途径使用的对象称之为死去的对象,这些对象占用的内存就是我们进行垃圾回收的内存。那么如何判断对象已经死去呢?我们可以通过 引用计数器算法可达性分析算法 进行操作。

2.1 判断对象死去算法

2.1.1 引用计数器算法

引用计数器算法:就是给对象添加一个计数器,每当有地方引用它时,计数器加1; 当引用失效就减1。当计数器为0 就表示该对象不能在被使用。但是这种算法无法解决循环依赖的问题。
关于循环依赖具体介绍 请参考 西门吹牛 的一篇博客 https://www.cnblogs.com/gudi/p/6414420.html?utm_source=itdadao&utm_medium=referral

2.1.2 可达性分析算法

可达性分析算法 通过一系列的GCRoots 为起始点向下进行搜索 搜索的路径就是引用链,当一个对象到GCRoots没有任何一条引用链相连(也称之为GC Roots 到这个对象不可达)。那么该对象就可以被判定为回收的对象。
如图 3-1 所示,对象 object 5、object 6、object 7 虽然互相有关联,但是它们到 GC Roots 是不可达的,所以它们将会被判定为是可回收的对象。

java 中可作为GCRoots 的对象包括下面几种:
虚拟机栈中引用的对象方法区中类静态属性引用的对象方法区中常量池中引用的对象本地方法栈引用的对象

2.3 回收方法区

方法区又称之为HotSpot 虚拟机中的永久代,它的垃圾收集包括2部分内容:废弃常量无用的类
和java堆中对象回收类似,当一个字面常量没有被任何地方引用时 在进行垃圾收集的时候该常量内存就会被进行回收。
无用的类需要满足3个条件:

  1. 改类的所有的实例都已经被回收
  2. 加载该类的ClassLoader已经被回收
  3. 该类对应的java.lang.Class 对象没有在任何地方被引用 并且无法通过反射访问该类的方法

2.4 垃圾收集算法

标记清除算法

标记清除算法 就是先标记要回收的对象,标记完成后回收所有被标记的对象。
它的缺点有2个:
1 效率低 标记和清除的过程效率都不高。
2 会产生大量的内存碎片。
内存碎片太多会导致无法分配比较大的对象,而频繁的执行垃圾收集的操作。

复制算法

复制算法会将内存分为相等2块, 然后只是使用其中一块 。当使用的一块内存用完时,将存活的对象复制另一块内存中。然后在将已经使用过的内存清理掉。
这种算法优点是效率高。
缺点是要牺牲一半的内存空间。

在我们的java虚拟机中 新生代的对象都是朝生夕死 的,其内存并没有按照 1:1 进行划分 而是将内存分为 一个较大的Eden 和 2块较小的Survivor 默认情况下 Eden和Survivor 大小比例是 8:1

标记整理算法

标记整理算法和标记清除算法标记过程一样,区别是在进行清理的时候会将存活的对象整理到一起 然后清理掉存活对象以外的内存。
这样做的好处是减少内存碎片的产生。

分代收集算法

分代收集算法是根据对象存活周期的不同将内存划分为几块。这样做的好处是我们可以根据不同代的特点采用不同的垃圾收集算法。java堆分为新生代老年代
新生代: 新生代中会有大量的对象死去只有少量存活 所以采用复制算法
老年代: 对象存活率高,所以采用 标记清除标记整理算法。

2.5 HotSpot的算法实现

2.6 垃圾收器

我们上面讲了很多垃圾收集算法 而垃圾收集器就是我们这些算法的具体实现。在java虚拟机中我们通过各种垃圾收集器来完成内存的回收。
Serial 收集器
单线程作用于新生代的收集器 ,版本比较老的收集器。
ParNew 收集器
并行(多线程版)的作用于 新生代的收集器,它是Serial 收集器多线程版
Parallel Scavenge 收集器
并行的作用于新生代的收集器。 采用复制算法 可以设置吞吐量
Serial Old 收集器
单线程的作用于老年代收集器, 是Serial 收集器老年代版本收集器。
Parallel Old 收集器
并行作用于老年代收集器 ,是Parallel Scavenge 收集器的老年代版本。
CMS 收集器
并行并发的作用于新生代收集器,采用标记清除算法实现。
G1收集器
并行并发的作用于不同代的收集器,采用标记整理算法实现

3 什么时候回收

关于这个问题 书中通过内存分配和回收策略中进行详细的介绍。因为说到回收不得不说内存如何去进行分配。其实java 虚拟机就是帮我们处理了2件事情 给对象分配内存 和回收非配给对象的内存。
内存非配策略有以下几个

3.1 内存分配策略

在进行介绍之前我们要先说一下Minor GC和 Full GC 是什么? Minor GC 是新生代GC
就是发生在新生代垃圾收集操作。这个操作比较频繁回收速度也快。 Full GC/Major GC 发生在老年代的GC
一般最少执行一次Minor GC 该操作数据比较慢。一般会比Minor GC慢10倍

3.1.2 对象优先在Eden分配

大多数情况下对象在Eden区中分配,当Eden区没有足够的空间进行分配时 虚拟机将发动一次 Minor GC

3.1.2 大对象直接进入老年代

很长的字符串以及数组 我们称之为大对象,如过是大对象我们直接将其分配到老年代中。

3.1.3 长期存活的对象将进入老年代

每个对象都有一个年龄计数器 当年龄增加到一定程度后将会被晋升到老年代中。(默认是15岁)而年龄的判断是对象在Edne出生并经过一次Minor GC 后仍然存活并被Survivor 接受对象的的年龄为1 每经历一次MinorGC 年龄就增加1。

3.1.4 动态对象年龄判定

对象到达指定的年龄就进入老年代这个也不是绝对的。如果Survivor空间相同年龄对象大小总和大于Survivor空间的一半,那么年龄大于或等于该年龄的对象就可以直接进入老年代。

3.1.5 空间分配担保

在进行 Minor GC 前先判断老年代空间是否大于新生代所有对象的空间 如果大于则可以进行 MinorGC 如果不成立在检查 老年代空间是否大于晋升到老年代对象大小的空间。如果大于,如果大于就进行一次MinorGC 如果小于就进行一次Full GC。
我们的老年代就相当于新生代空间的担保人 。就想我们生活中的贷款一样,我们在贷款是一般需要有一个担保人,当你没有偿还能力是就让担保人替你偿还。我们通过这种方式来判断是否要执行Full GC

【深入理解Java虚拟机学习笔记】第三章 垃圾收集器与内存分配策略相关推荐

  1. java虚拟机读书笔记 第三章 垃圾收集器和内存分配策略

    java虚拟机读书笔记 第三章 垃圾收集器和内存分配策略 GC需要完成的三件事情:哪些内存需要回收.什么时候回收.如何回收 垃圾回收器在对堆进行回收前,首先要确定那些对象存活,哪些对象已经死去,判断的 ...

  2. JVM之(Shenandoah、ZGC收集器)(基于《深入理解Java虚拟机》之第三章垃圾收集器与内存分配策略)(下)

    上一篇丹丹学妹已经给我讲了七种经典的GC器,那到底怎么样的GC器才能称的上"完美"? asda这就涉及到了衡量GC器性能的三项最重要的指标:①.内存占用②.吞吐量 ③.低时延 ,有 ...

  3. 第三章 垃圾收集器与内存分配策略

    第三章 垃圾收集器与内存分配策略 前言: 3.1 概述 3.2 对象已死? 3.2.1 引用计数算法 3.2.2 可达性分析算法 3.2.3 再谈引用,四种引用类型 3.2.4 生存还是死亡 3.3 ...

  4. 第三章 垃圾收集器与内存分配策略(待续)

    概述 对象已死吗 转载于:https://www.cnblogs.com/hzzjj/p/9825911.html

  5. 《深入理解Java虚拟机》-----第3章 垃圾收集器与内存分配策略

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来. 3.1 概述 说起垃圾收集(Garbage Collection,G ...

  6. 【深入理解Java虚拟机学习笔记】第二章 Java 内存区域与内存溢出异常

    最近想好好复习一下java虚拟机,我想通过深读 [理解Java虚拟机 jvm 高级特性与最佳实践] (作者 周志明) 并且通过写一些博客总结来将该书读薄读透,这里文章内容仅仅是个人阅读后简短总结,加强 ...

  7. 《深入理解Java虚拟机》笔记3——7种垃圾收集器

    如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现.**Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商.版本的虚拟机所提供的垃圾收集器都可能会有很大差别 ...

  8. 深入理解 Java 虚拟机 学习笔记

    第二章 Java 内存区域与内存溢出异常 内存区域 -- from 姜志明 对象创建 加载类 若已经在内存中则跳过. 类加载完以后就可以确定对象所需的空间大小 // TODO why? 分配内存 根据 ...

  9. 《深入理解JAVA虚拟机》学习日志----一、自动内存管理机制(2.垃圾收集器与内存分配策略)

    二.垃圾收集器与内存分配策略 前言:讨论的区域集中在Java堆和方法区中,而其他几个区域的内存分配和回收都具备确定性,所以不需过多考虑回收 的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了. ...

最新文章

  1. 瀚思首发三款产品 推动大数据安全战略布局
  2. pywinauto 记事本操作示例 移动鼠标 使用键盘 自动操作软件
  3. 存储过程结果更改编码_Docker安装Minio存储服务器详解
  4. 【数据库】关系数据库理论学习
  5. 并行算法第四讲:比较器网络选择和排序
  6. 深度学习分类只有正样本_自动调制分类:一种深度学习的方法
  7. linux命令(43):awk的使用技巧
  8. 【优化算法】Iterative映射和单纯形法的改进灰狼优化算法(SMIGWO)【含Matlab源码 1746期】
  9. 多媒体计算机技术的核心技术是,计算机多媒体的核心技术与发展
  10. 利用python通过拟合优度检验判别数据是否为正态分布
  11. 红外遥控系统原理附51单片机软件解码程序
  12. Word、Excel、PPT等图标异常解决方案
  13. 浅谈ThingJs之对象查询方法
  14. Linux基础系统优化及常用命令
  15. CMM是什么?什么是 “能力成熟度模型”?
  16. 【论文阅读】Structured Pruning Learns Compact and Accurate Models
  17. H3C(28)——IPSec
  18. JSP同步请求和html+ajax异步请求的两种方式
  19. JIRA 集成Devops\fisheye注意gn
  20. Open Policy Agent

热门文章

  1. python列表元祖字典集合运算_Python基础5:列表 元祖 字典 集合 Json
  2. java程序在内存中的存储分配
  3. android打包成apk会屏蔽注解,Android解决混淆打包之后注解被去掉的问题-Go语言中文社区...
  4. rust腐蚀深井_深井开采中的地压现象致因分析及措施_高光
  5. java 工厂模式_软件设计工厂模式使用场景介绍及java举例(附源码)
  6. wechat.php+获取昵称,微信后台代码,获取用户昵称
  7. python def函数报错详解_python自定义函数def的应用详解
  8. C++接收字符串数组_Java 中初始化数组
  9. angular ts 表格_angular表格内容滚动实现
  10. 计算机采用逻辑元件的发展顺序是,全国计算机等级考试一级选择题以及答案