• 引入垃圾回收
  • 哪些内存需要回收?
  • 引用计数法
  • 可达性分析
  • 如何回收
  • Marking 标记
  • Normal Deletion 清除
  • Deletion with Compacting 压缩
  • 为什么需要分代收集?
  • JVM的分代
  • 新生代
  • 老年代
  • 永久代
  • 分代垃圾收集过程详述

引入垃圾回收

程序计数器、 虚拟机栈、 本地方法栈3个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。 每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的(尽管在运行期会由JIT编译器

进行一些优化,但在本章基于概念模型的讨论中,大体上可以认为是编译期可知的),因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了。 而Java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间时才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾收集器所关注的是这部分内存-----《深入理解Java虚拟机》

自动垃圾回收机制就是寻找Java堆中的对象,并对对象进行分类判别,寻找出正在使用的对象和已经不会使用的对象,然后把那些不会使用的对象从堆上清除。

自动垃圾回收机制就是要解决三个问题:

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

哪些内存需要回收?

引用计数法

对于第一个问题,也就是判断是否还需要使用,最简单的方法就是通过目前是否有引用指向这个对象,如果没有就说明这个对象不会再被使用了,如果有就说明这个对象可能还会继续被使用,这种通过引用是否存在的方法就叫做引用计数法,但这个方法存在一个问题就是无法解决对象循环引用的问题,因此又出现了可达性分析的方法来判断对象是否可以被会回收。

可达性分析

这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

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

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 方法区中类静态属性引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象。

如何回收

垃圾收集器通常会帮我们在后台自动进行垃圾回收。关于具体的回收过程只要有以下这些步骤

  • Step 1: Marking 标记

第一步就是标记,也就是垃圾收集器会找出那些需要回收的对象所在的内存和不需要回收的对象所在的内存,并把它们标记出来,简单的说,也就是先找出垃圾在哪

所有堆中的对象都会被扫描一遍,以此来确定回收的对象,所以这通常会是一个相对比较耗时的过程

  • Step 2: Normal Deletion

    垃圾收集器会清除掉上一步标记出来的那些需要回收的对象区域

存在的问题就是碎片问题:

标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程

序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

  • Step 2a: Deletion with Compacting 压缩

    由于简单的清除可能会存在碎片的问题,所以又出现了压缩清除的方法,也就是先清除需要回收的对象,然后再对内存进行压缩操作,将内存分成可用和不可用两大部分

为什么需要分代收集?

就像前文所述,标记对象和压缩内存的过程在JVM中是不高效的,分配的对象越多,垃圾收集的时间就越长。但是,经过一些经验型性的统计分析表明,一个程序中大部分对象都是短命的!

下图就是一个类似的统计数据,纵坐标表示分配对象所占用的内存大小,横坐标表示自分配对象过去的时间

从图中我们看到,大部分对象没活多久就死了,存活较久的只是少类对象

JVM的分代

为了增大垃圾收集的效率,所以JVM将堆进行分代,分为不同的部分,一般有三部分,新生代,老年代和永久代

新生代

所有新new出来的对象都会最先出现在新生代中,当新生代这部分内存满了之后,就会发起一次垃圾收集事件,这种发生在新生代的垃圾收集称为Minor collections。这种收集通常比较快,因为新生代的大部分对象都是需要回收的,那些暂时无法回收的就会被移动到老年代。

Stop the World事件-所有minor garbage collections都是Stop the World事件,也就是意味着所有的应用线程都需要停止,直到垃圾回收的操作全部完成。类似于

“你妈妈在给你打扫房间的时候,肯定也会让你老老实实地在椅子上或者房间外待着,如果她一边打扫,你一边乱扔纸屑,这房间还能打扫完?”

老年代

老年代用来存储那些存活时间较长的对象。一般来说,我们会给新生代的对象限定一个存活的时间,当达到这个时间还没有被收集的时候就会被移动到老年代中。老年代区域的垃圾收集叫做major garbage collection

Major garbage collection也是一个Stop the World事件。通常Major garbage collection都相对比较慢,因为老年代的收集包括了对所有对象的收集,也就是同时需要收集新生代和老年代的对象。

永久代

The Permanent generation contains metadata required by the JVM to describe the classes and methods used in the application. The permanent generation is populated by the JVM at runtime based on classes in use by the application. In addition, Java SE library classes and methods may be stored here.

Classes may get collected (unloaded) if the JVM finds they are no longer needed and space may be needed for other classes. The permanent generation is included in a full garbage collection.

分代垃圾收集过程详述

我们已经知道垃圾回收所需要的方法和堆内存的分代,那么接下来我们就来具体看一下垃圾回收的具体过程

  • 第一步 所有new出来的对象都会最先分配到新生代区域中,两个survivor区域初始化是为空的

  • 第二步,当eden区域满了之后,就引发一次 minor garbage collection

  • 第三步,当在minor garbage collection,存活下来的对象就会被移动到S0survivor区域

  • 第四步,然后当eden区域又填满的时候,又会发生下一次的垃圾回收,存活的对象会被移动到survivor区域而未存活对象会被直接删除。但是,不同的是,在这次的垃圾回收中,存活对象和之前的survivor中的对象都会被移动到s1中。一旦所有对象都被移动到s1中,那么s2中的对象就会被清除,仔细观察图中的对象,数字表示经历的垃圾收集的次数。目前我们已经有不同的年龄对象了。

  • 第五步,下一次垃圾回收的时候,又会重复上次的步骤,清除需要回收的对象,并且又切换一次survivor区域,所有存活的对象都被移动至s0。eden和s1区域被清除。

  • 第六步,重复以上步骤,并记录对象的年龄,当有对象的年龄到达一定的阈值的时候,就将新生代中的对象移动到老年代中。在本例中,这个阈值为8.

  • 第七步,接下来垃圾收集器就会重复以上步骤,不断的进行对象的清除和年代的移动

  • 最后,我们观察上述过程可以发现,大部分的垃圾收集过程都是在新生代进行的,直到老年代中的内存不够用了才会发起一次 major GC,会进行标记和整理压缩。

深入解析Java垃圾回收机制的更多相关文章

  1. 成为Java GC专家(3)—如何优化Java垃圾回收机制

    为什么需要优化GC 或者说的更确切一些,对于基于Java的服务,是否有必要优化GC?应该说,对于所有的基于Java的服务,并不总是需要进行GC优化,但前提是所运行的基于Java的系统,包含了如下参数或 ...

  2. 成为JavaGC专家(3)—如何监控Java垃圾回收机制(转载)

    原文:http://www.importnew.com/3146.html 为什么需要优化GC 或者说的更确切一些,对于基于Java的服务,是否有必要优化GC?应该说,对于所有的基于Java的服务,并 ...

  3. 【转载】Java垃圾回收机制

    原文地址:http://www.importnew.com/19085.html Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联 ...

  4. 【转】深入理解 Java 垃圾回收机制

    深入理解 Java 垃圾回收机制   一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  5. 深入理解java垃圾回收机制

    深入理解java垃圾回收机制---- 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  6. Java垃圾回收机制_(转载)

    Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给 ...

  7. java 垃圾回收机制 引用类型

    Java语言的一个重要特性是引入了自动的内存管理机制,使得开发人员不用自己来管理应用中的内存.C/C++开发人员需要通过malloc/free 和new/delete等函数来显式的分配和释放内存.这对 ...

  8. 【Java】Java垃圾回收机制

    Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给 ...

  9. Java垃圾回收机制的工作原理

    Java垃圾回收机制的工作原理 [博主]高瑞林 [博客地址]http://www.cnblogs.com/grl214 获取更多内容,请关注小编个人微信公众平台: 一.Java中引入垃圾回收机制的作用 ...

随机推荐

  1. C语言(记录)——内存相关_2:内存的编址与管理

    本文是基于嵌入式的C语言 --------------------------------------------------------------------------------------- ...

  2. Jni中C++和Java的参数传递(转)

    如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用VC++6.0实现JNI的最简单的例子 ...

  3. The Euler function(线性筛欧拉函数)

    /* 题意:(n)表示小于n与n互质的数有多少个,给你两个数a,b让你计算a+(a+1)+(a+2)+......+b; 初步思路:暴力搞一下,打表 #放弃:打了十几分钟没打完 #改进:欧拉函数:具体 ...

  4. Jungle Roads(最小生成树)

    Jungle Roads Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...

  5. Eddy's picture(最小生成树)

    Eddy's picture Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...

  6. Circle

    Circle   Memory Limit: 32768KB   64bit IO Format: %lld & %llu Status Description Your task is so ...

  7. rsync远程数据同步工具的使用

    准备工作 虚拟机1: 192.168.24.41, 用于搭建rsync服务器 虚拟机2: 192.168.26.68, 用于搭建rsync客户端 虚拟机1和虚拟机2均为centos7; 1. 检查虚拟 ...

  8. SQL——按照季度,固定时间段,分组统计数据

    最近在工作中接到了一个需求,要求统计当月以10天为一个周期,每个周期的数据汇总信息.假设有一张表如下: 表table_test中 ID           AMOUNT         CREATE_ ...

  9. 如何成为一个javascript高手【转载】

      原文网址: http://www.cnblogs.com/keva/p/how-to-become-a-javascript-badass.html 英文网址:http://www.clientc ...

  10. Intellij导入子项目时,maven列表子项目灰色不可用---解决方法

    导入子项目的module时,左侧project目录中有一个module图标右下角没有小蓝点,maven管理列表该module为灰色(表明未被管理),尝试几次后终于找到解决方案. 贴一张调好过后的图 第 ...