漫画:什么是JVM的垃圾回收?

—————  第二天  —————

————————————


下面我们一起来研究这三个问题。

问题1:哪些是需要回收的?

首先我们需要知道如何哪些垃圾需要回收?判断对象是否需要回收有两种算法。一种是引用计数算法、一种是可达性分析算法。

引用计数算法

引用计数算法很简单,它通过记录对象被引用的次数从而判断该对象的重要程度。如果该对象被其它对象引用,则它的引用计数加一,如果删除对该对象的引用,那么它的引用计数就减一,当该对象的引用计数为0时,那么该对象就会被回收。

引用计数存在什么问题呢?当有两个对象相互引用时,由于它们互相引用对方所以计数都不为零,这就会导致这两个对象无法回收。

所以,Java虚拟机采用的是另一种方法来判断对象是否存活,它就是可达性分析算法。


可达性分析算法

可达性分析算法,首先要确定一系列根对象(GC Roots),并从根对象为起点根据对象之间的引用关系搜索出一条引用链(Reference Chain),在引用链的对象就存活,而不在引用链的对象就认定为可回收对象。

有一个比喻十分恰当:可达性分析算法就好比是在清洗葡萄串,我们可以从一根枝提起一大串葡萄,他们就像一串引用链,而没有和引用链相连的对象就像是散落在池子里的葡萄,可以回收。


  • 虚拟机栈中引用的对象(正在运行的方法使用到的变量、参数等)

  • 方法区中类静态属性引用的对象(static关键字声明的字段)

  • 方法区中常量引用的对象,(也就是final关键字声明的字段)

  • 本地方法栈中引用的对象(native方法)

  • Java虚拟机内部的引用。(系统内部的东西当然能作为根了)


问题2:有哪些重要的垃圾回收算法?

学会判断内存中哪些垃圾需要回收后,我们就需要掌握几个重要的垃圾回收算法。

标记-清除算法

标记-清除法是最基本的一种垃圾回收算法,总的来说分为两步:

  • 标记

标记所有需要回收的对象(灰色),也就是在做垃圾的判定。

  • 清除

将标记为灰色的部分,清除掉。

需要注意的是:所谓的清除,并不需要真正地把整个内存的字节进行清零操作,只需要把空闲对象的起始结束地址记录下来放入空闲列表里,表示这段内存是空闲的就行。

  • 优点速度快,只需要做个标记就能知道哪一块需要被回收,但是他的缺点也是致命的。

  • 他的主要缺点有两个:一是执行效率不稳定,二是会涉及到内存碎片化的问题

可能有人会问,碎片化是什么意思呢?上面所描述的这个栈,通过标记清除法虽然是清除了空间,但是清除出来的内存是大量的不连续内存碎片,像下面的这块对象,明明整体都有位,却因为不连续无法放入,这是标记-清除算法最大的缺点。

所谓标记复制算法和标记整理算法,都是对标记清除算法缺点的改进,所以才说标记清除算法是最基础的方式。

标记-整理算法

与标记-清除算法不同,标记-整理算法是移动式的。他会让所以存活的对象都向内存空间一端移动,然后清除到边界以外的内存。

  • 标记

  • 移动

是什么样的弊端呢?标记-整理算法涉及到了对象的移动,在整理阶段,由于移动了可用对象,需要去更新引用。效率就低了。

标记-复制算法

标记-复制算法,相比前面的比较不同,他将内存空间分为两块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,然后呢再清除正在使用的内存块中的所有对象。最后再交换两个内存的角色,最后完成垃圾回收。

大体来看可以分为 这么几个步骤:

  • 复制

  • 清空

  • 易位

不难看出,标记复制算法不需要标记算是提升了效率。此外他也不会参数碎片问题。

但是。标记复制算法的缺点也是十分明显的,它需要双倍空间。

问题3:垃圾回收的具体流程是怎样的?

既然说JVM虚拟机不会单独采用某种算法,而是会结合三种算法让他们协同工作,其具体的实现就是java虚拟机里的分代垃圾回收机制。

上图所示,就是Java堆内存的划分。为什么需要这么划分区域呢?那是因为我们的java对象寿命都是不同的,有的可能需要长时间使用,而有的可能用完就可以丢去。于是我们可以根据其生命周期的不同特点,进行不同的垃圾回收策略。

总的来说,新生代的垃圾回收比较频繁,老年代很久才触发一次垃圾回收。新生代处理的都是一些朝生夕死的对象,而老年代回收的是更有价值的,会长时间存活的对象。

举个很好理解的例子:新生代处理垃圾,就像是处理生活日用垃圾,而老年代处理的垃圾,更像是过年大扫除,家里实在太多垃圾了来一次重清理。大扫除清理的垃圾,都是在家中存放时间较长的,往往可能曾经很受用,如今退役了先放着过年再打扫清除掉。

每一次,我们创建一个对象,都会在伊甸园区占据一定内存大小,渐渐地伊甸园就满了。当我们再要创建对象时,就会发现空间不够了。

这时,就会触发一次垃圾回收,新生代触发的垃圾回收有个称呼叫做MinorGC

MinorGC触发后,伊甸园区就会对各个对象进行可达性分析,从而知道哪些对象应该作为垃圾被清理。

MinorGC在这里采取的是标记复制算法,它将有用的对象存放到幸存区to,然后把伊甸园中的对象清除掉。

进入幸存区的幸运儿,将会被标记上一个“幸运值”,代表他们抗住了多少次清理。

最后,幸存区to和幸存区from还需要交互一下位置,这里不是指物理位置交换,而是说,它俩的定义发生了交换,下次就是左边那个为幸存区to,右边的为幸存区from了。

换句话说,幸存区to始终是空的。

我们再模拟多几次,加深一下印象:

假如又进来了不少对象,伊甸园又满了!

那就会触发一次MinorGC,把幸存者移步到幸存区to,其他一律清空。

最后别忘了,幸存区from和幸存区to又要再交换一下”位置“。

...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#日期格式

关于C#中日期DateTime的格式转换代码如下: PS:请忽略Log.v(); 这个是自定义的日志方法…… DateTime dt DateTime.Now; Log.v(dt.ToString("D"));//2017年1月23日 Log.v(dt.ToString("d"));//2017/1/23 Log.v(dt.ToString("…

48张图|手摸手教你性能监控、压测和调优

本文主要内容一、何为压力测试1.1、 大白话解释性能压测是什么:就是考察当前软件和硬件环境下,系统所能承受的最大负荷,并帮助找出系统的瓶颈所在。性能压测的目的:为了系统在线上的处理能力和稳定性维持在一个标准范围内&#xf…

java中intvalue_Java Float类intValue()方法与示例

java中intvalue浮动类intValue()方法 (Float class intValue() method) intValue() method is available in java.lang package. intValue()方法在java.lang包中可用。 intValue() method is used to return the value denoted by this Float object converted to type int (by…

JTable demo

简单讲就是在没有使用layout manager的时候用setSize,在使用了layout manager 的时候用setPreferredSize 并且setPreferredSize通常和setMinimumSize、setMaximumSize联系起来使用setSize()是你手动来设置组件的大小 Dimension 类封装单个对象中组件的宽度和高度&am…

C#操作Cookie

简单的存储Cookie和获取Cookie例子 public string SaveCookie(string name) {// 登陆成功要将必要数据存储到 Cookie 里HttpCookie httpCookie new HttpCookie("cookie");// 设置过期时间httpCookie.Expires DateTime.Now.AddHours(1);// 设置姓名httpCookie.Valu…

Java生成随机数的4种方式,以后就用它了!

作者 | 王磊来源 | Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG_Stone)在 Java 中,生成随机数的场景有很多,所以本文我们就来盘点一下 4 种生成随机数的方式,以…

Java LinkedList addFirst()方法与示例

LinkedList addFirst()方法 (LinkedList addFirst() method) This method is available in package java.util.LinkedList. 软件包java.util.LinkedList中提供了此方法。 This method is used to insert an object at the initial or beginning stage of the linked list. 此方…

二层冗余网络引起的问题

1.广播风暴 环路会引起广播风暴 网络中主机会收到重复数据帧 2.MAC地址表震荡 环路引起的MAC地址表震荡,交换机死机 3.有可能收到重复的流量转载于:https://www.cnblogs.com/hotshotgg/p/4537817.html

Everything是如何搜索的

写在前面 使用了Everything之后,一直对他的搜索速度感兴趣,在网上也看了很多对其原理的揭秘,终于有空找了个源码研究了一下,原理就是对NTFS的USN特性进行使用。 原理 详细解释我参照别人家的博客来一段: 当扇区的文…

漫话:如何给女朋友解释String对象是不可变的?

String的不变性String在Java中特别常用&#xff0c;相信很多人都看过他的源码&#xff0c;在JDK中&#xff0c;关于String的类声明是这样的&#xff1a;public final class String implements java.io.Serializable, Comparable<String>, CharSequence { }可以看到&#…

XenServer 6.5实战系列之十一:Install Update For XenServer 6.5

为了保证XenServer主机的安全及功能的更新&#xff0c;在企业环境中我们需要定期的到Citrix官网或通过XenCenter进行下载和更新。今天我们会从在线和离线两种不同的方法进行Update的安装。更新补丁之前请务必阅读对应Update的相关资料、注意事项和做好备份。1. 离线安装更新在…

机器学习 属性_属性关系文件格式| 机器学习

机器学习 属性Today, we will be looking at the use of attribute relation file format for machine learning in java and we would be writing a small java code to convert the popularly used .csv file format into the arff (Attribute relation file format). This f…

C#标记废弃方法

一、普通用法 在C#中&#xff0c;如果一个方法我们不再使用&#xff0c;我们可以将其标记为“废弃”的方法&#xff0c;只需要在方法前&#xff0c;加一个[Obsolete]即可&#xff1b; [Obsolete] public void BiuBiuBiu(){// 嘿嘿嘿 }废弃方法并非不能使用&#xff0c;而是在…

阿里二面一问MySQL就开始野了,抓着底层原理不撒手啊!

最近项目增加&#xff0c;缺人手&#xff0c;面试不少&#xff0c;但匹配的人少的可怜。跟其他组的面试官聊&#xff0c;他也抱怨了一番&#xff0c;说候选人有点儿花拳绣腿&#xff0c;回答问题不落地&#xff0c;拿面试最常问的MySQL来说&#xff0c;并不只是懂“增删改查”、…

[转]“Ceph浅析”系列之(—)—Ceph概况

转载自&#xff1a;http://yizhaolingyan.net/?p11本文将对Ceph的基本情况进行概要介绍&#xff0c;以期读者能够在不涉及技术细节的情况下对Ceph建立一个初步印象。2.1 什么是Ceph&#xff1f;Ceph的官方网站Ceph.com上用如下这句话简明扼要地定义了Ceph&#xff1a;“Ceph…

关于C#监视剪贴板信息

##1、常规方法 在C#中&#xff0c;有一个常规检测剪贴板的方法&#xff0c;用的是 System.Windows.Forms.Clipboard&#xff1b; 使用起来很简单&#xff0c;代码如下&#xff1a; /// <summary> /// 设置剪贴板的文本内容 /// </summary> /// <param name&qu…

图解Java中的18 把锁!

乐观锁和悲观锁独占锁和共享锁互斥锁和读写锁公平锁和非公平锁可重入锁自旋锁分段锁锁升级&#xff08;无锁|偏向锁|轻量级锁|重量级锁&#xff09;锁优化技术&#xff08;锁粗化、锁消除&#xff09;乐观锁和悲观锁悲观锁悲观锁对应于生活中悲观的人&#xff0c;悲观的人总是想…

在CSS中使用not:first-child选择器

Introduction: 介绍&#xff1a; Well, selectors are a very common term to deal with while we are developing a website or web page. You might know quite a few of them and might as well be implementing them. You might also have noticed that all the selectors…

linux/unix 段错误捕获【续】

本文为“在C/C中捕获段错误&#xff0c;打印出错的具体位置”的续篇&#xff0c;进一步解决涉及动态链接库的情况。背景知识&#xff1a;linux/unix下动态链接库的基本原理/proc/pid/maps文件的基本格式动态链接库&#xff1a;在进程执行过程中动态加载&#xff0c;进程间可以共…

C#获取屏幕大小的“简单整理”。。

额…… 首先是有一个需求&#xff0c;两个显示器&#xff0c;程序自动获取自己所在的显示器大小&#xff0c;并显示到右下角。 我们都知道C#有一个Screen.PrimaryScreen.Bounds&#xff0c;可以获取屏幕的完整尺寸&#xff0c;但是只能获取主显示器的尺寸&#xff0c;后来我发…