JVM的GC分为两个主要部分,第一部分是判断对象是否已死(堆内存的垃圾回收占主要部分,方法区(metaspace)的内存回收在最新的官方文档中未给出详细解释,暂时不做讨论范围),第二部分是对内存区进行回收用于下次的内存分配。

一、判断对象是否已死

  JDK 8的VM实现是Hotspot虚拟机,它采用的是可达性分析算法。

  a.引用计数算法

    给每个对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时计数器的值就减1。但在VM中它无法解决的一个问题就是循环引用问题(也是              Hotspot没有采用它的主要原因):

  

public class ReferenceCountingGC {
public Object instance = null;
private static final int _1MB = 1024 * 1024;
private byte[] size = new byte[_1MB]; //这个成员属性的意义在于占据堆内存,以便稍后观察JVM是否回收了了堆内存
public static void main(String[] args) {
ReferenceCountingGC obj1 = new ReferenceCountingGC(),obj2 = new ReferenceCountingGC();
obj1.instance = obj2;
obj2.instance = obj1; //这两行代码为循环引用的发生场景
obj1 = null;
obj2 = null; //这两行代码导致对象无法访问,但是他们对应的计数器值并不为0,如果采用的是引用计数算法,将不会发生堆内存回收
System.gc(); //垃圾回收发生在此行,分为新生代垃圾回收、堆内存和元空间的回收
} }

  b.可达性分析算法

  这个算法的基本思路就是通过一系列成为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链的时,则证明此对象是不可用的,即对象已死。

  

  Object5、Object6、Object7到GC Roots没有引用链的存在,因此这三个对象会回收。

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

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

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

  方法区中常量引用的对象

  方法区中变量引用的对象

  c.再谈引用

  判断一个对象是否已死,无论是引用计数算法还是可达性分析算法,它们都与引用有关,在JDK1.2以后,Java中的引用分为Strong Reference(强引用)、Soft Reference(软引用)、弱引用(Weak Reference)、虚引用(Phantom Reference):

  强引用就是指在程序代码中普遍存在的,类似“Object obj = new Object()”这类的引用,只要引用还存在,垃圾收集器永远不会回收掉被引用的对象。

  软引用是用来描述还有用但非必需的对象。对于软引用关联的对象,在系统将要发生内存溢出之前,将会把这些对象列进回收范围进行二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK1.2之后,提供了SoftReference类来实现软引用。

  弱引用也是来描述非必需对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次内存回收之前。在JDK1.2后,提供了WeakReference类来实现弱引用。

  虚引用的存在不会对被引用对象产生任何影响,为一个对象设置虚引用的目的就是能在这个对象被垃圾收集器回收时收到一个系统的通知。

二、内存回收算法

  a.标记-清除算法

  b.复制算法

  c.标记-整理算法

  d.分代收集算法

  现代的商业虚拟机都使用分代收集算法,即堆内存中的新生代采用复制算法,老年代采用标记-清除或者标记-整理算法。

  注:新生代和老年代的意义是相对于GC的而不是运行时数据区,不同GC对于堆内存的划分有所不同,垃圾回收的侧重点也不相同。

  The blue area in Figure 3-1, "Typical Distribution for Lifetimes of Objects" is a typical distribution for the lifetimes of objects. The x-axis is object lifetimes measured in bytes   allocated. The byte count on the y-axis is the total bytes in objects with the corresponding lifetime. The sharp peak at the left represents objects that can be reclaimed (in   other words, have "died") shortly after being allocated. Iterator objects, for example, are often alive for the duration of a single loop.

  Figure 3-1 Typical Distribution for Lifetimes of Objects

  

  To optimize for this scenario, memory is managed in generations (memory pools holding objects of different ages). Garbage collection occurs in each generation when the   generation fills up. The vast majority of objects are allocated in a pool dedicated to young objects (the young generation), and most objects die there. When the young           generation fills up, it causes a minor collection in which only the young generation is collected; garbage in other generations is not reclaimed. Minor collections can be        optimized, assuming that the weak generational hypothesis holds and most objects in the young generation are garbage and can be reclaimed. The costs of such              collections are, to the first order, proportional to the number of live objects being collected; a young generation full of dead objects is collected very quickly. Typically, some           fraction of the surviving objects from the young generation are moved to the tenured generation during each minor collection. Eventually, the tenured generation will fill up   and must be collected, resulting in a major collection, in which the entire heap is collected. Major collections usually last much longer than minor collections because a           significantly larger number of objects are involved.

Figure 3-2, "Default Arrangement of Generations, Except for Parallel Collector and G1" shows the default arrangement of generations (for all collectors with the exception   of the parallel collector and G1):

  Figure 3-2 Default Arrangement of Generations, Except for Parallel Collector and G1

    

  At initialization, a maximum address space is virtually reserved but not allocated to physical memory unless it is needed. The complete address space reserved for object   memory can be divided into the young and tenured generations.

  The young generation consists of eden and two survivor spaces. Most objects are initially allocated in eden. One survivor space is empty at any time, and serves as the   destination of any live objects in eden; the other survivor space is the destination during the next copying collection. Objects are copied between survivor spaces in this way   until they are old enough to be tenured (copied to the tenured generation).

  新生代中的对象在下面情况中进入老年代:

  大对象通过分配担保直接进入老年代(大对象大小的临界值根据不同GC而设定)

  长期存活的对象

  大对象直接进入老年代

  Minor GC后,Survivor仍然放不下

  动态年龄判断 ,大于等于某个年龄的对象超过了survivor空间一半 ,大于等于某个年龄的对象直接进入老年代

  

JVM学习二:垃圾收集(Garbage Collection,GC)机制的更多相关文章

  1. JVM总括二-垃圾回收:GC Roots、回收算法、回收器

    JVM总括二-垃圾回收:GC Roots.回收算法.回收器 目录:JVM总括:目录 一.判断对象是否存活 为了判断对象是否存活引入GC Roots,如果一个对象与GC Roots没有直接或间接的引用关 ...

  2. JVM学习二:JVM之GC算法和种类

    我们前面说到了JVM的常用的配置参数,其中就涉及了GC相关的知识,趁热打铁,我们今天就学习下GC的算法有哪些,种类又有哪些,让我们进一步的认识GC这个神奇的东西,帮助我们解决了C 一直挺头疼的内存回收 ...

  3. JVM笔记(二) 垃圾收集器(1)

    垃圾收集器 主要通过阅读<深入了解Java虚拟机>(周志明 著)和网络资源汇集而成,为本人学习JVM的笔记.同时,本文理论基于JDK 1.7版本,暂不考虑 1.8和1.9 的新特性,但可能 ...

  4. hive impala C++ Java垃圾回收 Garbage Collection GC

    hive impala impala  推荐每个节点内存  2^7~2^8GB Impala与Hive的比较 - 文章 - 伯乐在线 http://blog.jobbole.com/43233/ &l ...

  5. JVM学习笔记:虚拟机的类加载机制

    JVM类加载机制分两部分来总结: (1)类加载过程 (2)类加载器 一.JVM类加载过程 类的加载过程:加载 →连接(验证 → 准备 → 解析)→ 初始化. 类的生命周期:加载 →连接(验证 → 准备 ...

  6. python 之gc(回收机制)--garbage collection(GC垃圾回收)

    ######################引用计数######################### 引用计数:python 当中一种用来解决垃圾回收的策略之一 char 1个字节(2**8) in ...

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

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

  8. JVM学习记录-垃圾收集器

    先回顾一下上一篇介绍的JVM中常见几种垃圾收集算法: 标记-清除算法(Mark-Sweep). 复制算法(Copying). 标记整理算法(Mark-Compact). 分代收集算法(Generati ...

  9. JVM学习(二):垃圾回收

    我刚工作的时候问一个前辈,我们能针对JVM做出什么样的优化.前辈说,我们系统现在的性能并不需要调优,用默认的配置就能满足现在的需求了.我又问,那你为什么要看JVM相关的书呢?前辈微微一笑,悠悠地来了句 ...

随机推荐

  1. vs2015 c# winfrom应用程序打包成64位

    关于Winform打包过程在网上已有详细教程,参考:https://www.cnblogs.com/yinsq/p/5254893.html 此次工作中需要打包成64位的程序,网上没有查到方法,现在讲 ...

  2. sql习题及答案

    sql习题:http://www.cnblogs.com/wupeiqi/articles/5729934.html 习题答案参考:https://www.cnblogs.com/wupeiqi/ar ...

  3. jsp页面<%@ page报错问题

    eclipse中的web项目jsp页面<%@报错如下图所示: 解决办法: 在项目上右键→ Build Path → Configure Build Path... Libraries → add ...

  4. js的关于for的语句

    JavaScript for...in 语句 for...in 语句用于对数组或者对象的属性进行循环操作. for ... in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作. ...

  5. Spring———bean的创建方式,注入方式,复杂类型注入 概括

    Spring相关概念和类    1.IOC             inverse of control    控制反转   反转了创建对象的方式            以前:new 对象,管理和维护 ...

  6. QT学习教程

    原地址:http://www.devbean.NET/2012/08/qt-study-road-2-catelog/ 网上看到的不错的教程 本教程以qt5为主,部分地方会涉及qt4.据说非常适合qt ...

  7. C++对象模型复习

    本文写于2017-02-24,从老账号迁移到本账号,原文地址:https://i.cnblogs.com/EditPosts.aspx?postid=6440685 一:对象模型 C++面向对象的实现 ...

  8. 1.4 SQL函数

    1.调用聚合函数 sum:返回所有值的和/非重复数据的和 avg:平均数且忽略空值 min:最小值 max:最大值 count:计数函数 distinct:去不重复记录 2.数学函数 abs:绝对值 ...

  9. java中的常用特殊字符

    1.转义字符反斜杠(\) 我们知道html中大都是双标签,如果在标签内想要输出带有标签结束符的文本都必须进行转义,html中是采用对应的字符替换,如<可用<替换 在java当中,我们要转义 ...

  10. python builtin列表

    Python Builtin function获得通过 python3 -c "import builtins;ff=open('test.txt','w');strlist=[(i+'\n ...