判断大小简单算法_JVM GC算法
在判断哪些内存需要回收和什么时候回收用到GC 算法,本文主要对GC 算法进行讲解。
JVM垃圾判定算法
常见的JVM垃圾判定算法包括:引用计数算法、可达性分析算法。
引用计数算法(Reference Counting)
引用计数算法是通过判断对象的引用数量来决定对象是否可以被回收。
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。
优点:简单,高效,现在的objective-c用的就是这种算法。
缺点:很难处理循环引用,相互引用的两个对象则无法释放。因此目前主流的Java虚拟机都摒弃掉了这种算法。
举个简单的例子,对象objA和objB都有字段instance,赋值令objA.instance=objB及objB.instance=objA,除此之外,这两个对象没有任何引用,实际上这两个对象已经不可能再被访问,但是因为互相引用,导致它们的引用计数都不为0,因此引用计数算法无法通知GC收集器回收它们。
public class ReferenceCountingGC { public Object instance = null; public static void main(String[] args) { ReferenceCountingGC objA = new ReferenceCountingGC(); ReferenceCountingGC objB = new ReferenceCountingGC(); objA.instance = objB; objB.instance = objA; objA = null; objB = null; System.gc();//GC }}
运行结果
[GC (System.gc()) [PSYoungGen: 3329K->744K(38400K)] 3329K->752K(125952K), 0.0341414 secs] [Times: user=0.00 sys=0.00, real=0.06 secs] [Full GC (System.gc()) [PSYoungGen: 744K->0K(38400K)] [ParOldGen: 8K->628K(87552K)] 752K->628K(125952K), [Metaspace: 3450K->3450K(1056768K)], 0.0060728 secs] [Times: user=0.05 sys=0.00, real=0.01 secs] Heap PSYoungGen total 38400K, used 998K [0x00000000d5c00000, 0x00000000d8680000, 0x0000000100000000) eden space 33280K, 3% used [0x00000000d5c00000,0x00000000d5cf9b20,0x00000000d7c80000) from space 5120K, 0% used [0x00000000d7c80000,0x00000000d7c80000,0x00000000d8180000) to space 5120K, 0% used [0x00000000d8180000,0x00000000d8180000,0x00000000d8680000) ParOldGen total 87552K, used 628K [0x0000000081400000, 0x0000000086980000, 0x00000000d5c00000) object space 87552K, 0% used [0x0000000081400000,0x000000008149d2c8,0x0000000086980000) Metaspace used 3469K, capacity 4496K, committed 4864K, reserved 1056768K class space used 381K, capacity 388K, committed 512K, reserved 1048576KProcess finished with exit code 0
从运行结果看,GC日志中包含“3329K->744K”,意味着虚拟机并没有因为这两个对象互相引用就不回收它们,说明虚拟机不是通过引用技术算法来判断对象是否存活的。
可达性分析算法(根搜索算法)
可达性分析算法是通过判断对象的引用链是否可达来决定对象是否可以被回收。
从GC Roots(每种具体实现对GC Roots有不同的定义)作为起点,向下搜索它们引用的对象,可以生成一棵引用树,树的节点视为可达对象,反之视为不可达。
在Java语言中,可以作为GC Roots的对象包括下面几种:
•虚拟机栈(栈帧中的本地变量表)中的引用对象。•方法区中的类静态属性引用的对象。•方法区中的常量引用的对象。•本地方法栈中JNI(Native方法)的引用对象
真正标记以为对象为可回收状态至少要标记两次。
四种引用
强引用就是指在程序代码之中普遍存在的,类似"Object obj = new Object()"这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。
Object obj = new Object();
软引用是用来描述一些还有用但并非必需的对象,对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK1.2之后,提供了SoftReference类来实现软引用。
Object obj = new Object();SoftReference sf = new SoftReference(obj);
弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象,只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK1.2之后,提供了WeakReference类来实现弱引用。
Object obj = new Object();WeakReference wf = new WeakReference(obj);
虚引用也成为幽灵引用或者幻影引用,它是最弱的一中引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。在JDK1.2之后,提供给了PhantomReference类来实现虚引用。
Object obj = new Object();PhantomReference pf = new PhantomReference(obj);
JVM垃圾回收算法
常见的垃圾回收算法包括:标记-清除算法,复制算法,标记-整理算法,分代收集算法。
在介绍JVM垃圾回收算法前,先介绍一个概念。
Stop-the-World
Stop-the-world意味着 JVM由于要执行GC而停止了应用程序的执行,并且这种情形会在任何一种GC算法中发生。当Stop-the-world发生时,除了GC所需的线程以外,所有线程都处于等待状态直到GC任务完成。事实上,GC优化很多时候就是指减少Stop-the-world发生的时间,从而使系统具有高吞吐 、低停顿的特点。
标记—清除算法(Mark-Sweep)
之所以说标记/清除算法是几种GC算法中最基础的算法,是因为后续的收集算法都是基于这种思路并对其不足进行改进而得到的。标记/清除算法的基本思想就跟它的名字一样,分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
标记阶段:标记的过程其实就是前面介绍的可达性分析算法的过程,遍历所有的GC Roots对象,对从GC Roots对象可达的对象都打上一个标识,一般是在对象的header中,将其记录为可达对象;
清除阶段:清除的过程是对堆内存进行遍历,如果发现某个对象没有被标记为可达对象(通过读取对象header信息),则将其回收。
不足:
•标记和清除过程效率都不高•会产生大量碎片,内存碎片过多可能导致无法给大对象分配内存。
复制算法(Copying)
将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。
现在的商业虚拟机都采用这种收集算法来回收新生代,但是并不是将内存划分为大小相等的两块,而是分为一块较大的 Eden 空间和两块较小的 Survior 空间,每次使用 Eden 空间和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中还存活着的对象一次性复制到另一块 Survivor 空间上,最后清理 Eden 和 使用过的那一块 Survivor。HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了内存的利用率达到 90 %。如果每次回收有多于 10% 的对象存活,那么一块 Survivor 空间就不够用了,此时需要依赖于老年代进行分配担保,也就是借用老年代的空间。
不足:
•将内存缩小为原来的一半,浪费了一半的内存空间,代价太高;如果不想浪费一半的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。•复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。
标记—整理算法(Mark-Compact)
标记—整理算法和标记—清除算法一样,但是标记—整理算法不是把存活对象复制到另一块内存,而是把存活对象往内存的一端移动,然后直接回收边界以外的内存,因此其不会产生内存碎片。标记—整理算法提高了内存的利用率,并且它适合在收集对象存活时间较长的老年代。
不足:
效率不高,不仅要标记存活对象,还要整理所有存活对象的引用地址,在效率上不如复制算法。
分代收集算法(Generational Collection)
分代回收算法实际上是把复制算法和标记整理法的结合,并不是真正一个新的算法,一般分为:老年代(Old Generation)和新生代(Young Generation),老年代就是很少垃圾需要进行回收的,新生代就是有很多的内存空间需要回收,所以不同代就采用不同的回收算法,以此来达到高效的回收算法。
新生代:由于新生代产生很多临时对象,大量对象需要进行回收,所以采用复制算法是最高效的。
老年代:回收的对象很少,都是经过几次标记后都不是可回收的状态转移到老年代的,所以仅有少量对象需要回收,故采用标记清除或者标记整理算法。
判断大小简单算法_JVM GC算法相关推荐
- 【JVM】对象存活判定算法、GC算法、STW、GC种类详解
[JVM]对象存活判定算法.GC算法.STW.GC种类详解 文章目录 [JVM]对象存活判定算法.GC算法.STW.GC种类详解 GC主要关注的区域 垃圾标记阶段:对象存活判断 标记阶段:引用计数算法 ...
- (六)JVM成神路之GC基础篇:对象存活判定算法、GC算法、STW、GC种类详解
引言 经过前面五个章节的分析后,对于JVM的大部分子系统都已阐述完毕,在本文中则开始对JVM的GC子系统进行全面阐述,GC机制也是JVM的重中之重,调优.监控.面试都逃不开的JVM话题. 在前面分析J ...
- 双目立体视觉匹配算法-----SAD匹配算法、BM算法、SGBM算法、GC算法
一. SAD算法 1.算法原理 SAD(Sum of absolute differences)是一种图像匹配算法.基本思想:差的绝对值之和.此算法常用于图像块匹配,将每个像素对应数值 ...
- 判断大小简单算法_优化 | 贪婪算法有多好?Submodularity告诉你
文章作者:乔杰 责任编辑:苏向阳 本文转载自知乎专栏 贪婪算法有多好?Submodularity告诉你 原文链接:https://zhuanlan.zhihu.com/p/52512602 文章发表于 ...
- 判断大小简单算法_算法浅谈——人人皆知却很多人写不对的二分法
本文首发于公众号:TechFlow 1 二分法可以说是鼎鼎大名,哪怕是没有学过编程的同学,也许说不上来二分法这个名字,但是对于其中的精髓应该都是有所了解的.不了解的同学也没关系,我一句话就能交代清楚: ...
- JVM 知识梳理 (二) GC算法
文章目录 一.前言 二.判定哪些对象需要被GC 引用计数法Reference Count 可达性算法(引用链法Tracing) 三.GC算法 标记-清除 标记-压缩 复制算法 总结 分代收集 补充:H ...
- java标志清理_JVM内存管理之GC算法精解(五分钟让你彻底明白标记/清除算法)...
相信不少猿友看到标题就认为LZ是标题党了,不过既然您已经被LZ忽悠进来了,那就好好的享受一顿算法大餐吧.不过LZ丑话说前面哦,这篇文章应该能让各位彻底理解标记/清除算法,不过倘若各位猿友不能在五分钟内 ...
- 简单描述GC垃圾标记算法和垃圾收集算法
前言 使用通俗的语言简单回顾一下JVM GC的垃圾标记算法和垃圾收集算法. 一.什么是Garbage(辣鸡)? 通俗的认为,不被任何在用的引用所指向的资源称为垃圾.硬件资源是有限的,如何准确的标识出垃 ...
- 深入理解 Java 虚拟机 - 你了解 GC 算法原理吗
来自:好好学Java 虚拟机系列文章 深入理解 Java 虚拟机(第一弹) - Java 内存区域透彻分析 深入理解 Java 虚拟机(第二弹) - 常用 vm 参数分析 深入理解 Java 虚拟机- ...
最新文章
- Data-Mediator专题之属性回调
- java 文件通配符_Java中泛型通配符的使用方法示例
- django-redis中redis.conf配置详细说明
- Java LocalDate类| minus()方法与示例
- sqlserver java odbc_Java JDBC------------------ODBC(SQLServer)链接
- C++工作笔记-getter/setter方法中大佬的风格
- Python turtle库绘制奥运五环
- Hibernate中createCriteria即QBC查询的详细用法 .Hibernate中createCriteria即QBC查询的详细用法 ....
- capslock键英语怎么读_改造你的CapsLock键,让你效率提升近10倍!
- 用ultraiso安装linux系统教程,使用UltraISO制作ubuntu安装u盘启动盘图文教程
- 程序员通病:小厂薪资低,想跳槽,又担心面试过不了!
- Elasticsearch之高亮进阶-高性能高亮器, 让Elasticsearch飞一会儿
- 《Design of Computer Programs》学习笔记(2 - 1)Back of the Envelope - Lesson 2
- excel切片器_用Excel切片器做自动化表格,动态呈现,瞬间高大上
- Ubuntu开发环境_TLP电源管理模块、禁用笔记本触摸板
- dockers安装ES
- 生信技能9 - 生物信息分析必须掌握的生物学基本概念(建议收藏)
- java导出excel报表_java怎样导出Excel报表呢?
- 计算机硬件故障分为哪几种,计算机常见故障可分为硬件和软件故障,具体介绍...
- 清华大学计算机网络教程mobi,计算机网络使用教程 清华大学出版社.ppt
热门文章
- java锁_Java锁
- selenium自动化测试_您如何使用Selenium来计算自动化测试的投资回报率?
- oracle 容器运行_Oracle应用容器云的自由
- rest资源设计_REST资源何时应获得其自己的地址?
- jasperreports_JasperReports:棘手的部分
- sql limit 子句_Java 8流中的常见SQL子句及其等效项
- 什么是通用字符名称?_通用名称
- wso2 esb_使用WSO2 ESB进行邮件内容过滤
- netflix测试能不能看_Netflix监管者测试–引入知事,准官员
- Spring Framework中的作用域代理