Java GC算法
转自:http://blog.csdn.net/heyutao007/article/details/38151581
1、JVM内存组成结构
JVM内存结构由堆、栈、本地方法栈、方法区等部分组成,结构图如下所示:
1)堆
所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制。堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,Survivor由FromSpace和ToSpace组成,结构图如下所示:
新生代。新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例。
旧生代用于存放新生代中经过多次垃圾回收(也即Minor GC)仍然存活的对象
2)栈
每个线程执行每个方法的时候都会在栈中申请一个栈帧,每个栈帧包括局部变量区和操作数栈,用于存放此次方法调用过程中的临时变量、参数和中间结果
3)本地方法栈
用于支持native方法的执行,存储了每个native方法调用的状态
4)方法区
存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。JVM用持久代(或者叫做永久代,PermanetGeneration)来存放方法区,可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值。
在过去(自定义类加载器还不是很常见的时候),类大多是”static”的,很少被卸载或收集,因此被称为“永久的(Permanent)”。同时,由于类class是JVM实现的一部分,并不是由应用创建的,所以又被认为是“非堆(non-heap)”内存。
在JDK8之前的HotSpot JVM,存放这些”永久的”的区域叫做“永久代(permanent generation)”。永久代是一片连续的堆空间,在JVM启动之前通过在命令行设置参数-XX:MaxPermSize来设定永久代最大可分配的内存空间,默认大小是64M(64位JVM由于指针膨胀,默认是85M)。永久代的垃圾收集是和老年代(old generation)捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集。不过,一个明显的问题是,当JVM加载的类信息容量超过了参数-XX:MaxPermSize设定的值时,应用将会报OOM的错误。
永久代在JDK8中被完全的移除了。所以永久代的参数-XX:PermSize和-XX:MaxPermSize也被移除了。
在JDK8中,classe metadata(the virtual machines internal presentation of Javaclass),被存储在叫做Metaspace的native memory。一些新的flags被加入:
-XX:MetaspaceSize,class metadata的初始空间配额,以bytes为单位,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当的降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize(如果设置了的话),适当的提高该值。
-XX:MaxMetaspaceSize,可以为class metadata分配的最大空间。默认是没有限制的。
-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为class metadata分配空间导致的垃圾收集
-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为class metadata释放空间导致的垃圾收集
默认情况下,class metadata的分配仅受限于可用的native memory总量。可以使用MaxMetaspaceSize来限制可为class metadata分配的最大内存。当class metadata的使用的内存达到MetaspaceSize(32位clientVM默认12Mbytes,32位ServerVM默认是16Mbytes)时就会对死亡的类加载器和类进行垃圾收集。设置MetaspaceSize为一个较高的值可以推迟垃圾收集的发生。
介绍完了JVM内存组成结构,下面我们再来看一下JVM垃圾回收机制。
2.1、引用计数(reference counting)
原理:此对象有一个引用,则+1;删除一个引用,则-1。只用收集计数为0的对象。
缺点: (1)无法处理循环引用的问题。如:对象A和B分别有字段b、a,令A.b=B和B.a=A,除此之外这2个对象再无任何引用,那实际上这2个对象已经不可能再被访问,但是引用计数算法却无法回收他们。(2)引用计数的方法需要编译器的配合。编译器需要为此对象生成额外的代码。如赋值函数将此对象赋值给一个引用时,需要增加此对象的引用计数。还有就是,当一个引用变量的生命周期结束时,需要更新此对象的引用计数器。
引用计数的方法由于存在显著的缺点,实际上并未被JVM所使用。
2.2、复制(copying)
原理:把内存空间划分为2个相等的区域,每次只使用一个区域。垃圾回收时,遍历当前使用区域,把正在使用的对象复制到另外一个区域。
优点:不会出现碎片问题。
缺点:
(1)暂停整个应用。
(2)需要2倍的内存空间。
2.3、标记-清扫(Mark-and-sweep)
原理:对于“活”的对象,一定可以追溯到其存活在堆栈、静态存储区之中的引用。这个引用链条可能会穿过数个对象层次,算法基于有向图,采用深度优先搜索。
第一阶段:从GC roots开始遍历所有的引用,对有活的对象进行标记。
第二阶段:对堆进行遍历,把未标记的对象进行清除。
优点:解决了循环引用的问题。
缺点:
(1)暂停整个应用;
(2)会产生内存碎片。
(3)不管你这个对象是不是可达的,即是不是垃圾,都要在清楚阶段被检查一遍,非常耗时.
sun前期版本就是用这个技术。
2.4、标记-压缩(Mark-Compact)
第一阶段:同标记-清扫,标记活的对象,
第二阶段:这个阶段将所有做了标记的活动对象整理到堆的底部
优点:
(1)避免标记扫描的碎片问题;
(2)避免停止复制的空间问题。
2.5、分代(generational collecting)
原理:基于对象生命周期分析得出的垃圾回收算法。把对象分为年轻代、年老代、持久代,对不同的生命周期使用不同的算法(2-3方法中的一个即4自适应)进行回收。
J2SE1.2以后使用此算法
JVM分别对新生代和旧生代采用不同的垃圾回收机制
2.5.1、新生代的GC(Minor GC):
指发生在新生代的垃圾收集动作,因为 Java 对象大多都具备朝生夕灭的特性,所以 Minor GC 非常频繁,一般回收速度也比较快。
新生代通常存活时间较短,因此基于Copying算法来进行回收,所谓Copying算法就是扫描出存活的对象,并复制到一块新的完全未使用的空间中,对应于新生代,就是在Eden和FromSpace或ToSpace之间copy。新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发GC。当连续分配对象时,对象会逐渐从eden到survivor,最后到旧生代,
2.5.2、旧生代的GC(Major GC / Full GC):
指发生在老年代的 GC。旧生代与新生代不同,对象存活的时间比较长,比较稳定,因此采用标记(Mark)算法来进行回收,所谓标记就是扫描出存活的对象,然后再进行回收未被标记的对象,回收后对用空出的空间要么进行合并,要么标记出来便于下次进行分配,总之就是要减少内存碎片带来的效率损耗。
MajorGC 的速度一般会比 Minor GC 慢 10倍以上。
Thinking in java给java gc取了一个罗嗦的称呼:“自适应、分代的、停止-复制、标记-扫描”式的垃圾回收器。
导致Gc的情况:
1、tenured被写满
2、perm被写满
3、System.gc()的显式调用。
4、上一次GC之后heap的各域分配策略动态变化。
Java GC算法的更多相关文章
- jvm系列(三):java GC算法 垃圾收集器
GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计 ...
- Java GC算法 垃圾收集器
GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为"GC",它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. ...
- JAVA GC算法详解
生存还是死亡 对象是否需要被垃圾收集器回收主要有两种方式:引用计数法和可达性分析算法 引用计数法 给对象添加一个引用计数器,每当有一个地方引用他的时候,计数器的数值就+1,当引用失效时,计数器就-1: ...
- jvm系列三、java GC算法 垃圾收集器
原文链接:http://www.cnblogs.com/ityouknow/p/5614961.html 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 ...
- Java虚拟机(二):Java GC算法 垃圾收集器
概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计数器.虚拟机栈.本地方 ...
- [Java基础]-- Java GC 垃圾回收器的分类和优缺点
https://blog.csdn.net/high2011/article/details/80177473?utm_source=blogxgwz2 参考:elasticsearch实战-使用G1 ...
- Java垃圾回收(java GC)
一.GC的阶段 对每个对象而言,垃圾回收分为两个阶段:finalization和reclamation. finalization: 指运行这个对象的finalize的方法. reclamation: ...
- JVM学习(4)——全面总结Java的GC算法和回收机制
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 一些JVM的跟踪参数的设置 Java堆的分配参数 -Xmx 和 –Xms 应该保持一个什么关系,可以让系统的 ...
- Java虚拟机:GC算法深度解析
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 在前面的文章里介绍了可达性分析算法,它为我们解决了判定哪些对象可以回收的问题,接下来就该我们的垃圾收集算法出场了.不同的垃圾收集算法有各自 ...
随机推荐
- 完美的Linux之【navi】使用笔记
今天要说的是才上线才两天,就已经获得超过1000星.开发者是一位来自巴西的小哥Denis Isidoro. 开发的工具navi Linux用户的日常困惑 新命令 用完就忘 ? 一时想不起来命令的单词怎 ...
- redis命令行命令
配置文件设置密码认证 修改redis.conf去掉#requirepass foobared前面的#,foobared就是密码,可以进行修改 redis命令设置密码认证config set requi ...
- Android 虚线实现绘制 - DashPathEffect
前言: 通过view绘制虚实线,采用Android自带API--DashPathEffect.具体使用请参考更多的链接,这里只是讲解. 构造函数 DashPathEffect 的构造函数有两个参数: ...
- MySQL --13 主从复制
目录 一.主从复制简介 二.主从复制原理 三.主从复制搭建实战 四.主从复制基本故障处理 五.延时从库 企业案例: 模拟环境 一.主从复制简介 复制是 MySQL 的一项功能,允许服务器将更改从一个实 ...
- nutz包的学习
参考资料: 1.http://www.nutzam.com/core/nutz_preface.html
- 洛谷4206/NOI2005T4 聪聪和可可 期望DP+记忆化搜索
题意:给出n个点m条边的无向图,两个主角聪聪和可可开始分别在S点和T点.聪聪想吃掉可可,每次由匆匆先行动后来可可行动.聪聪的行动是选他到可可的最短路上的点走最多两步(如果最短路有几条就选编号最小的走) ...
- OtterCTF - Reverse - Msg Me This
原文地址:Msg Me This 题目 Category: Reverse Engineering Points: 500 Solves: 15 Description: Rick created a ...
- jquery 小知识
$("p:eq(0)") :表p标签的第一个元素 $("p:eq(1)") :表p标签的第二个元素
- 非阻塞套接字与IO多路复用(转,python实现版)
非阻塞:指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回.epoll工作在非阻塞模式时,才会发挥作用. 我们了解了socket之后已经知道,普通套接字实现的服务端的缺陷:一次只能服务一个 ...
- loj2542 「PKUWC2018」随机游走 MinMax 容斥+树上高斯消元+状压 DP
题目传送门 https://loj.ac/problem/2542 题解 肯定一眼 MinMax 容斥吧. 然后问题就转化为,给定一个集合 \(S\),问期望情况下多少步可以走到 \(S\) 中的点. ...