JVM垃圾回收机制【简单介绍】[通俗易懂]

JVM垃圾回收机制【简单介绍】[通俗易懂]Java虚拟机(JVM)垃圾回收机制JVM中的垃圾回收计数是采用的一种自适应的技术(可以通过其工作方式将它“啰嗦地”称为:自适的、分代的、停止-复制、标记-清扫式垃圾回收器)在讲Java虚拟机的自适应回收机制前,有必要说一下其他比较单纯的垃圾回收机制,然后会比较容易地理解JVM的垃圾回收:1、引用计数一种简单但速度很慢的垃圾回收计数。​ 每个对象都含有一个引用计数器,当有引用连接至对…

大家好,又见面了,我是你们的朋友全栈君。

Java虚拟机(JVM)垃圾回收机制

JVM中的垃圾回收计数是采用的一种自适应的技术(可以通过其工作方式将它“啰嗦地”称为:自适的、分代的、停止-复制、标记-清扫式垃圾回收器)

在讲Java虚拟机的自适应回收机制前,有必要说一下其他比较单纯的垃圾回收机制,然后会比较容易地理解JVM的垃圾回收:

1、引用计数

一种简单但速度很慢的垃圾回收计数。

​ 每个对象都含有一个引用计数器,当有引用连接至对象时,引用计数加 1 ;当引用离开作用域或者被置为null时,引用计数减 1 。垃圾回收器会在含有全部对象的列表上遍历,当发现某个对象的引用计数为 0 时,就释放其占用的空间。

​ 引用计数常用来说明垃圾收集的工作方式,但似乎从未被应用于任何Java虚拟机的实现中。

缺点:

  • 虽然管理引用计数开销不大,但这种开销在整个程序的生命周期中是持续发生的。
  • 如果对象之间存在循环引用,可能会出现“对象应该被回收,但是其引用计数却不等于 0 ”的情况,且定位如此交互自引用的对象组对于垃圾回收器来说所需的工作量极大

2、找到所有“活”的对象

​ 对于一些更快(回收性能更优秀)的垃圾回收技术,依据的思想:**对于任何“活着”的对象,一定能最终追溯到其存活在堆栈或静态存储区之中的引用。 **

​ JVM便是在基于此种方式采用的一种自适应的垃圾回收技术。不过对于如何处理找到的存活对象,这取决于不同的Java虚拟机实现。

  1. “停止-复制”

    ​ 先停止程序的运行,然后把所有存活的对象从当前堆复制到另一个堆中,其中没有被复制的对象都是“死”的,便是需要清除、释放的垃圾了。

    优点:

    • 当对象复制到新堆时,在新堆中保持紧凑排列,可以简单、方便地分配新空间。

    缺点:

    • “复制-回收”并不属于后台回收模式,该种模式下需要事先停止程序运行。即垃圾回收动作发生时候,程序会被暂停。
    • 效率不高,原因如下:
      1. 需要有两个堆,然后在两个堆之间来回折腾,需要维护的空间比实际的多了一倍。
      2. 程序进入稳定状态时,可能只会产生少量的垃圾,但此时复制式垃圾回收器还是会把几乎所有内存从一处复制到另一处,非常浪费。
  2. “标记-清扫”

    ​ 从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象;每当找到一个存活对象,便会给对象设一个标记。只有全部标记工作完成时候,才会开始清理动作。

    优点:

    • 清理过程中,没有标记的对象将被释放,不用进行任何复制动作

    缺点:

    • 清理后剩下的堆空间是不连续的,如果希望得到连续空间的话,需要重新整理剩下的对象。

3、JVM中自适应的垃圾回收机制

​ 在这里讨论的Java虚拟机中,内存分配以较大的“块”为单位;当对象比较大时,会占用单独的块。

​ 有了块的概念之后,我们可以对“复制-回收”的回收机制做一定的改进。之前的“复制-回收”要求在释放旧有对象之前,必须将所有存活对象从旧堆复制到新堆中,这会导致大量的内存复制行为;有了块之后,我们可以往废弃或闲置的块中复制对象

​ 那如何判断某个块是不是闲置的呢?每个块都是用对应的一个代数(generation count)记录该块是否还存活;如果该块在某处被引用,其代数便会增加。

​ 垃圾回收器会定期地进行完整的清理动作——大型对象(占用单独的块)不会被复制,而含有小型对象的那些块便会被复制并整理。

​ 在这过程中,JVM会进行监视,如果所有对象都很稳定,垃圾回收器的效率降低了,就切换到“标记-清扫”方式;而当“标记-清扫”下堆空间出现很多碎片时,便会切换回“停止-复制”方式。(所以知道为什么叫他“自适的、分代的、停止-复制、标记-清扫式垃圾回收器”了吧……)

Java虚拟机的回收机制介绍的差不多了,也只是比较表面的介绍,之后有机会、有能力的话再写写更加详细些的,嘻嘻。

参考文献:
《Java编程思想 Thinking in Java》 Bruce Eckel 著

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/133433.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 都能看懂的LIS(最长上升子序列)问题[通俗易懂]

    都能看懂的LIS(最长上升子序列)问题[通俗易懂]LIS问题介绍:首先来说一下什么是LIS问题:有一个长为n的数列a0,a1,……,a(n-1)。请求出这个序列中最长的上升子序列的长度。上升子序列指的是对于任意的i<j都满足ai<aj的子序列,该问题被称为最长上升子序列(LIS,LongestIncreasingSubsequence)的著名问题。举个栗子:给你一个序列为(1,5,2,6,9,1…

  • 钩子函数是什么?(函数那个小钩子哪里调出来)

    什么是钩子函数?先来看一段百科:钩子函数是Windows消息处理机制的一部分,通过设置“钩子”,应用程序可以在系统级对所有消息、事件进行过滤,访问在正常情况下无法访问的消息。钩子的本质是一段用以处理系统消息的程序,通过系统调用,把它挂入系统。emmmm,认认真真读三遍。get关键词,在系统级对所有消息进行过滤,这是什么意思呢?是说钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一…

  • RPC协议底层原理与实现「建议收藏」

    RPC协议底层原理与实现「建议收藏」RPC协议基本组成在一个典型RPC的使用场景中,包含了服务发现、负载、容错、网络传输、序列化等组件,其中RPC协议就指明了程序如何进行网络传输和序列化。也就是说一个RPC协议的实现就等于一个非透明的RPC调用,如何做到的的呢?Client客户端Server服务端协议基本组成:    1.  地址:服务提供者地址;2.  端口:协议指定开放的端口;3.  运行服务:1.  netty(…

  • 自抗扰控制(ADRC)—— python 实战「建议收藏」

    自抗扰控制(ADRC)—— python 实战「建议收藏」本文利用跟踪微分器(TD)、扩张状态观测器(ESO)和非线性PID实现了受外扰的未知系统的控制,使得受控系统输出了期望信号。

  • 优化Linux的内核参数来提高服务器并发处理能力

    优化Linux的内核参数来提高服务器并发处理能力

  • 【STM32】NVIC中断优先级管理(中断向量表)

    【STM32】NVIC中断优先级管理(中断向量表)STM32F1xx官方资料:《STM32中文参考手册V10》-第9章中断和事件Cortex-M3内核支持256个中断,其中包含了16个内核中断(异常)和240个外部中断,并且具有256级的可编程中断设置。但是,STM32并没有使用CM3内核的全部东西,而是只用了它的一部分。STM32有84个中断,包括16个内核中断(异常)和68个可屏蔽中断,具有16级可编程的中断优先级。而STM32F10…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号