这篇文章主要从以下几个方面介绍垃圾收集的相关知识

  一、判断对象是否已死

  二、主流垃圾收集算法

  三、内存分配与回收策略

  本章节主要从以下几个思考点着手介绍垃圾回收的相关知识:哪些内存需要回收?什么时候回收?如何回收?这也是经典的学习一个知识点的3h方法:what? when? how?

上一个章节已经介绍jvm运行时数据区的内存分布,垃圾回收主要发生在堆这个区,也就是众多对象实例呆着的地方

一、如何判断对象已死?

  相信面试过高级java的工程师肯定遇到过面试官这样的问题:两个对象之间互相循环引用,如何回收?换句话说如何判断这两个对象已死?

  这里就引出了一个经典算法:引用计数法。是这样设计的:给对象添加一个引用计数器,每当这个对象被引用时,计数器值+1,引用失效时,计数值-1,任何时刻,计数为0

的对象就是不可能再被使用的对象

  回到上面的例子,它很难解决互相引用的对象这种情况,于是导致GC无法回收他们

  于是出现了另一个经典算法:可达性分析算法,基本思路是通过一系列的称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,

当一个对象到GC Roots没有任何引用链相连,或者称从GC Roots到这个对象不可达时,则证明这个对象是不可用的

  作为GC Roots的对象一般有以下几种:虚拟机栈中引用的对象,方法区中类静态属性引用的对象,方法区中常量引用的对象,本地方法栈中JNI引用的对象(这一种不太熟悉)

  关于java对引用的概念细分为强引用,软引用,弱引用,虚引用的细节,可以阅读该书了解,在此不再介绍

二、几种常见的垃圾收集算法

  1、Mark-Sweep

  标记-清除算法,分为标记,清除两个阶段,首先标记出所有需要回收的对象,标记完成后统一回收

  不足:效率不高;回收后产生大量不连续的内存碎片。碎片太多的话,需要分配大对象时,无法找到足够的连续内存而不得不提前触发新一轮的垃圾收集动作

  2、Copying

  复制算法,大多商业虚拟机都采用这种收集算法回收新生代,具体的在第三点内存分配会讲到

  3、Mark-Compact

  标记-整理算法。一般使用于老年代

  4、Generational Collection

  分代收集算法。当前商业虚拟机的垃圾收集都采用分代收集算法,一般是把Java堆分为新生代和老年代,根据各自特点采用最适当的收集算法。

三、内存分配与回收策略

  Java的自动内存管理机制可以归结为解决了两个问题:给对象分配内存以及回收分配给对象的内存。Java的内存分配策略并不是绝对的或者固定的,这取决于

当前使用的垃圾收集器组合,以及虚拟机中与内存分配相关的参数设置,接下来讲的是最为普遍的内存分配规则

  (1)对象优先在Eden区分配

  新生代区域一般被分为较大的Eden空间和两块较小的Survivor空间(通常称为From和To),HotSpot虚拟机默认Edon和两个Survivor的大小比例是8:1:1,

新创建的对象一般会在Edon和From中,当Edon区没有足够的空间进行分配时,将触发一次Minor GC,前面讲过大多数对象是朝生夕死的,因此Minor GC非常频繁

当一次Minor GC过后,仍然存活的对象会一次性复制到To区域中,然后清理掉Edon和From;这时候注意,From和To将交换角色,现在新的To是清理后的From

因此To区域总能保证每次Minor GC后留有一定的空间容纳尚存活的对象

  (2)长期存活的对象将进入老年代

  虚拟机给每个对象都定义了一个对象年龄(Age)计数器,在Edon出生的对象经过第一次Minor GC后仍然存活,并能在Survivor容纳的话Age将设为1,在Survivor区

每熬过一次Minor GC,Age+1,当Age达到设置的参数值-XX:MaxTenuringThreshold(默认值15),将晋升老年代,关于晋升老年代的条件并非一定要达到这种情况,

java虚拟机有动态对象年龄判定策略,具体可阅读本书3.6.4细节

  (3)大对象直接进入老年代

  所谓大对象指的是需要大量连续内存空间的对象,最典型的如很长的字符串以及数组,经常出现大对象意味着很可能内存中还有不少空间时就得提前触发垃圾收集

以获取足够的连续空间来安置他们。

  (4)触发Full GC的条件

  Full GC的速度一般比Minor GC慢10倍以上,触发一次Full GC经常会伴随一次Minor GC,一种触发条件为,一次Minor GC发生后将要晋升为老年代的对象大小超过

老年代现有剩余空间大小,这种情形不难想象。java的老年代空间分配担保细节可细读3.6.5节知晓,此处不再细说

最后上图一张作为结尾,一目了然:

JVM系列(二) — Java垃圾收集介绍的更多相关文章

  1. JVM系列二(垃圾收集算法).

    一.标记-清除算法(Mark-Sweep) 这种算法分为"标记"和"清除"两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. Mar ...

  2. jvm系列 (二) ---垃圾收集器与内存分配策略

    垃圾收集器与内存分配策略 前言:本文基于<深入java虚拟机>再加上个人的理解以及其他相关资料,对内容进行整理浓缩总结.本文中的图来自网络,感谢图的作者.如果有不正确的地方,欢迎指出. 目 ...

  3. Java 虚拟机系列二:垃圾收集机制详解,动图帮你理解

    前言 上篇文章已经给大家介绍了 JVM 的架构和运行时数据区 (内存区域),本篇文章将给大家介绍 JVM 的重点内容--垃圾收集.众所周知,相比 C / C++ 等语言,Java 可以省去手动管理内存 ...

  4. JVM系列三(垃圾收集器).

    一.概述 1. 哪些内存需要回收 上篇文章 我们介绍了 Java 内存运行时区域的各个部分,其中程序计数器.虚拟机栈.本地方法栈三个区域随线程而生,随线程而灭,在这几个区域内就不需要过多考虑回收的问题 ...

  5. JVM系列(二):JVM的内存模型

    深入理解JVM内存模型    Java虚拟机在执行Java程序的过程中,把它所管理里的内存划分了不同的数据类型区域,作为一名开发者,我们需要了解jvm的内存分配机制以及这些不同的数据区域各自的作用. ...

  6. jvm系列(九):Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  7. jvm系列(六):Java服务GC参数调优案例

    本文介绍了一次生产环境的JVM GC相关参数的调优过程,通过参数的调整避免了GC卡顿对JAVA服务成功率的影响. 这段时间在整理jvm系列的文章,无意中发现本文,作者思路清晰通过步步分析最终解决问题. ...

  8. jvm系列(五):Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  9. jvm系列二内存结构

    二.内存结构 整体架构 1.程序计数器 作用 用于保存JVM中下一条所要执行的指令的地址 特点 线程私有 CPU会为每个线程分配时间片,当当前线程的时间片使用完以后,CPU就会去执行另一个线程中的代码 ...

随机推荐

  1. python学习第三天格式化输出%s %d

    编程语言为什么要格式化输出吗,一般print()就够了,有些复杂的格式输出比较麻烦,用格式化输出更加高效, info=""" ---------------------- ...

  2. 一个简单的winform程序调用webservices

    本文原创,如需转载,请标明源地址,谢谢合作!http://blog.csdn.net/sue_1989/article/details/6597078 本文的编写IDE为VSTS2008和.NET F ...

  3. 常见前端面试题http部分

    1.常见http状态码 100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息 200 OK 正常返回信息 20 ...

  4. parse_str()和http_build_query()的使用

    <?php $_html = array(); $_html['action1'] = 'action1'; $_html['action2'] = 'action2'; echo http_b ...

  5. C Primer Plus 学习 第四章

    字符串与格式化输入/输出 函数 strlen() 关键字 const 利用#define 和 const创建符号常量 #include <stdio.h> #include <str ...

  6. OkHttp源码剥离导入到eclipse中

    1.里面有两个类关于Android版本的我稍微修改过了,没有用的. 2.可以直接导入eclipse中,maven里面的jar包可能还有不需要的冗余,可以自己去剔除. https://github.co ...

  7. mongdb 简介以及安装

    1.什么是MongoDB?  MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.在高负载的情况下,添加更多的节点,可以保证服务器性能.MongoDB 旨在为WEB应用提供 ...

  8. Maven开始

    1:加入Maven插件: 这句话的意思是: 从本地仓库找到相应的jar包 <localRepository>F:\RepMaven</localRepository 2:创建一个Ma ...

  9. Oracle 的trim,ltrim,rtrim函数的区别

    该函数共有两种作用:第一种,即大家都比较熟悉的去除空格.例子:--TRIM去除指定字符的前后空格SQL> SELECT TRIM(' dd df ') FROM dual;TRIM('DDDF' ...

  10. Word中页码及目录、参考文献的制做方法

    1.页码从正文开始 1.要想从哪里显示第一页,就在这页的前一页的最后一行最后的地方,插入分隔符---下一页2.然后在你想显示第一页的那一页双击页脚处,点击取消掉“链接到前一条页眉”.(这是为了取消原来 ...