| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> JVM垃圾收集回收 -> 正文阅读 |
|
[Java知识库]JVM垃圾收集回收 |
垃圾收集是编程语言在设计时需要考虑的问题,垃圾收集最早起源于LISP语言,有很多语言都是支持垃圾收集的,如Python、Go、PHP、Js、Lua、Java、C#、D等, 不支持垃圾回收的语言有c/c++等。 ? 所以垃圾收集不是Java一个要面对的问题,这是个通用的技术点,这里我们只讨论Java相关的垃圾收集。 一、JVM需要回收的区域JVM规范定义了运行时数据区域分为5个部分,分别为堆、方法区、虚拟机栈、本地方法栈、程序计数器。其中虚拟机栈、本地方法栈、程序计数器都是伴随线程生命周期关联,随线程产生和消失,这3个区域的的回收直接跟随线程即可。而堆和方法区不一样,里面的内容是动态变化的,由程序的具体内容决定,所以这两个区域的回收需要动态执行。垃圾回收之前,需要将能够回收的垃圾找出来,就需要有算法来计算哪些对象是存活的,哪些是垃圾。 二、垃圾识别算法垃圾收集之前必须要知道哪些对象是垃圾,才能进行后续的收集工作。当前使用的较多的垃圾识别算法有2种,分别是引用计数法(reference counting)和可达性分析法(Roots tracing)。 引用计数法引用计数是GC中早期的策略,在这种算法下,每一个在堆中的对象都有一个计数关联,当一个对象被创建后,每当他的引用被赋值给另一个变量时,计数就会加1,每当引用这个对象的变量生命周期结束后,计数就会减1,这样就能知道有多少地方引用着对象,当引用计数为0时就表明这个对象已经可以被回收了。引用计数法的优势是可以很快的执行,缺点就是如果发生了循环引用,对象就无法被回收,所以想要使用引用计数法,一定要解决循环依赖计数的问题。 可达性分析法可达性分析算法是根据离散数学图论作为理论基础,该算法将程序中的所有引用关系建模成图,图由GC Root根节点开始,向下建立所有引用关系,形成引用链(reference chain),当所有的图建立完成后,如果发现有对象不在图中,也就是GC Root到这些对象不可达,那么这些对象就是无人引用的对象,也就是需要回收的垃圾。GC Root在对象图之外,是特别定义的起点,不可能被其他对象引用。 在Java中,可以作为gc root的对象有4种: 三、Java中引用类型无论是引用计数法还是可达性分析法,都和对象的引用的关系有关,Java根据引用的关系强弱划分了4个层次,分别为
四、方法区的垃圾回收方法区中需要回收的内容通常是无用的常量和无用的类型,无用的常量可以使用可达性分析算法来回收,对于无用的类的回收则需要满足以下3个条件: 五、JVM常用的垃圾收集算法引用计数法可以直接使用引用计数法来进行垃圾回收,随时监控对象的引用数量,进行回收,但是使用这种算法需要解决循环引用的问题。主流的Java虚拟机没有使用这种算法。 标记清除法(Mark-Sweep)标记清除算法分为标记和清除2阶段操作,标记阶段直接使用可达性分析算法扫描所有的对象,标记处需要回收的垃圾,清除阶段将标记出的对象清理回收,这种算法简单直接,不需要进行对象的移动,只需对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记清除算法直接回收不存活的对象,因此会造成内存碎片。 复制算法(Coping)为了解决标记清除算法的内存碎片缺陷,复制算法被提出来了,复制算法将可用的内存空间划分为大小相等的2块区域,运行时只会使用其中一块,在触发垃圾回收时,通过可达性分析算法计算出所有存活对象,然后将他们复制到另一块空闲区域,?完成一次回收,复制算法解决了内存碎片的问题,但是他对内存空间的浪费较大,同时如果对象存活较多时,效率会较低。 标记整理算法(Mark-Compact)?为了解决复制算法的内存利用率低的问题,标记整理算法被提出来了,分为标记和整理2阶段,标记阶段通过可达性分析算法将内存区域所有对象打上标记,区分出存活对象和回收对象,整理阶段将存活对象全部移动到内存的一端,剩下的空间就是可用区域了,他解决了复制算法的内存利用率低的弊端,但是需要付出复制对象的代价。 分代收集算法(generation collection)分代收集算法是目前绝大多数数Java虚拟机采用的回收算法,分代回收算法的前提是JVM将堆划分为新生代(young generation)和老年代(old generation),默认大小比值为1:2,其中新生代又被分为Eden和Survivor From(s0)和Survivor To(s1),默认大小比例为8:1:1。 新生代主要采用的算法是复制算法(区域划分是8:1:1不是1:1),运行时,新产生的对象放入新生代的Eden区,在合适实际会触发Minor GC(不一定是Eden满了才触发),然后将Eden中存活的对象放入s0,如果s0满了,就将Eden和s0中存活对象复制到s1中,(如果s1空间不够,就将对象存放到老年代去,不要存放到s1了)此时s0就被清空了,然后交换s0和s1地址,如果Eden中又发生Minor GC,就将存活对象复制到s0,如此往复。 老年代主要采用的回收算法是标记整理算法,当老年代内存到达一定值时,触发Major GC,也叫Full GC,老年代里面都是一些存活率较高的对象,使用标记整理算法,内存利用率较高。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 9:15:56- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |