深入解析Java垃圾回收机制
- 引入垃圾回收
- 哪些内存需要回收?
- 引用计数法
- 可达性分析
- 如何回收
- 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垃圾回收机制的更多相关文章
- 成为Java GC专家(3)—如何优化Java垃圾回收机制
为什么需要优化GC 或者说的更确切一些,对于基于Java的服务,是否有必要优化GC?应该说,对于所有的基于Java的服务,并不总是需要进行GC优化,但前提是所运行的基于Java的系统,包含了如下参数或 ...
- 成为JavaGC专家(3)—如何监控Java垃圾回收机制(转载)
原文:http://www.importnew.com/3146.html 为什么需要优化GC 或者说的更确切一些,对于基于Java的服务,是否有必要优化GC?应该说,对于所有的基于Java的服务,并 ...
- 【转载】Java垃圾回收机制
原文地址:http://www.importnew.com/19085.html Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联 ...
- 【转】深入理解 Java 垃圾回收机制
深入理解 Java 垃圾回收机制 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...
- 深入理解java垃圾回收机制
深入理解java垃圾回收机制---- 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...
- Java垃圾回收机制_(转载)
Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给 ...
- java 垃圾回收机制 引用类型
Java语言的一个重要特性是引入了自动的内存管理机制,使得开发人员不用自己来管理应用中的内存.C/C++开发人员需要通过malloc/free 和new/delete等函数来显式的分配和释放内存.这对 ...
- 【Java】Java垃圾回收机制
Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给 ...
- Java垃圾回收机制的工作原理
Java垃圾回收机制的工作原理 [博主]高瑞林 [博客地址]http://www.cnblogs.com/grl214 获取更多内容,请关注小编个人微信公众平台: 一.Java中引入垃圾回收机制的作用 ...
随机推荐
- javascript 之作用域链-07
复习作用域 上一节我们说到作用域:是指变量可以访问的范围,他规定了如何查找变量,以及确定当前执行代码对变量的访问权限:也说到静态作用域即词法作用域,是在编译阶段决定变量的引用(由程序定义的位置决定,和 ...
- 直方图均衡化C++实现
直方图均衡化在图像增强方面有着很重要的应用.一些拍摄得到的图片,我们从其直方图可以看出,它的分布是集中于某些灰度区间,这导致人在视觉上感觉这张图的对比度不高.所以,对于这类图像,我们可以通过直方图均衡 ...
- ASP.NET Core 认证与授权[4]:JwtBearer认证
在现代Web应用程序中,通常会使用Web, WebApp, NativeApp等多种呈现方式,而后端也由以前的Razor渲染HTML,转变为Stateless的RESTFulAPI,因此,我们需要一种 ...
- 用编写一个简单的记事本(C#实现)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- Windows环境下多线程编程原理与应用读书笔记(4)————线程间通信概述
<一>线程间通信方法 全局变量方式:进程中的线程共享全局变量,可以通过全局变量进行线程间通信. 参数传递法:主线程创建子线程并让子线程为其服务,因此主线程和其他线程可以通过参数传递进行通信 ...
- jsoup从表单中取数据
表单的格式如下 <td>user</td> <td>cc</td> </tr> <tr> <td>pass</ ...
- C# into子句
可使用 into 上下文关键字创建临时标识符,将 group.join 或 select 子句的结果存储至新标识符. 此标识符本身可以是附加查询命令的生成器. 有时称在 group 或 select ...
- AngularJS学习篇(十九)
AngularJS Bootstrap 可以在你的 AngularJS 应用中加入 Twitter Bootstrap,你可以在你的 <head>元素中添加如下代码: <link r ...
- G彩娱乐网一个程序员到一个销售高手的心路历程
0.引言 我大学本科读的是理工科,后来毕业以后,我逐渐走上了程 序员的道路.每天面对电脑一行一行的敲代码,这被我们程序员们戏称为"搬砖头",因为我们所做的事跟民工搬砖头砌墙本质上是 ...
- 一款非常推荐的用户界面插件----EasyUI
前 言 easyui是一种基于jQuery的用户界面插件集合. easyui为创建现代化,互动,JavaScript应用程序,提供必要的功能. 使用easyui你不需要写很多代码,你只需要 ...