热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

window更新产生的垃圾_11JVM垃圾回收(上)

引用计数法和可达性分析垃圾回收,就是将已经分配出去的,但却不在使用的内存回收回来,以便再次分配。在Java虚拟机语境下,垃圾
42245341ea905799170010c066159418.png

引用计数法和可达性分析

垃圾回收,就是将已经分配出去的,但却不在使用的内存回收回来,以便再次分配。在 Java 虚拟机语境下,垃圾指的是死亡的对象所占据的堆空间。下面就总结一下如何如何辨别一个对象是否死亡。

引用计数法:为每一个对象添加一个引用计数器,用来统计指向该对象的引用个数。如果某个对象的引用计数器为 0,则说明该对象已经死亡,便可以被回收了。

通过引用计数法来标记对象的死亡和存活的过程中,我们需要截获所有引用更新操作,并且相应的增减目标对象的引用计数器。这种方式除了需要额外的空间来存储计数器,以及繁琐的更新操作,引用计数法还有一个重大的漏洞:无法处理循环引用对象。比如:对象 A,B 互相引用,但是除此之外没有其他引用指向 A 或者 B。这种情况下 A,B 其实已经死亡,但是因为存在引用,所以不会被垃圾回收,造成内存泄露。

可达性分析:将一系列 GC Roots 作为初始存活对象集合,然后从该集合出发,探索所有能够被该集合引用的对象,并将其加入到该集合中,这个过程就是标记。标记的对象就是存活对象,未标记到的就是死亡的对象。

什么是 GC Roots 呢?可以暂时理解为由堆外指向堆内的引用,常见的有以下几种: 1:Java 方法栈帧中的局部变量 2:已加载的类的静态变量 3:JNI handles 4:已启动且未停止的 Java 线程

可达性分析解决了引用计数法无法检测循环引用的问题,但是本身也有自己的问题需要解决。比如在多线程环境下,其他线程可能会更新已经访问过的对象中的引用,从而造成误报(将引用设置为 null)或者漏报(将引用设置为未被访问过的对象)。

误报:导致新产生的垃圾对象未被回收。 漏报:导致原程序访问已经被回收的对象,可能导致 Java 虚拟机直接崩溃。

Stop-the-world 以及安全点

为了解决上述问题,在 Java 虚拟机里,采用 Stop-the-world 方式,停止其他非垃圾回收线程的工作,直到完成垃圾回收。这也造就了垃圾回收所谓的暂停时间 GC pause。

Java 虚拟机中的 Stop-the-world 是通过安全点(safepoint)机制来实现的。当 Java 虚拟机收到 Stop-the-world 请求时,它便会等待所有的线程到达安全点,才允许请求 Stop-the-world 的线程进行独占的工作。

安全点的作用不是让线程停下,而是找到让线程找到一个稳定的执行状态。在这个状态下,Java 虚拟机的堆栈不会发生变化。这样,垃圾回收期便能够安全地执行可行性分析。

垃圾回收的三种方式

第一种:清除。 把死亡对象所占据的内存标记为空闲内存,并记录在一个空闲列表中。当需要创建对象时,内存管理块便会从该空闲列表中寻找空闲内存,并划分给新建对象。

这种方式简单明了,但是却有两个缺点。第一:造成内存碎片。由于 Java 虚拟机的堆中对象必须是连续分布的,因此可能出现总空闲内存足够,但是无法分配的极端情况。第二:分配效率低。如果是连续的内存空间,可以通过指针加法来做分配。而对于这种空闲列表,Java 虚拟机则需要住个访问列表中的项,来查找能够存放入新建对象的空闲内存。

第二种:压缩。 把存活的对象聚集到内存区域的起始位置,从而留下一段连续的内存空间。这种做法解决了内存碎片化的问题,但是代价却是压缩算法的性能开销。

第三种:复制。 内存区域分为两等分,分别用两个指针 from 和 to 来维护,并且只是用 from 指针指向的内存区域来分配内存。当发生垃圾回收时,把存活的对象复制到 to 指针指向的内存区域,并且交换 from 指针和 to 指针的内容。这种方法同样解决了内存碎片化的问题,但是堆空间的使用效率及其地下,只用到了一半。

问答

Q:可达性分析a与b互为引用,这不是死循环了吗,为什么能被回收的

因为可达性分析只标记可达的,如果a和b都不可达,那么可达性分析标记不到,就当成垃圾回收了。

Q:对于为什么需要stw机制的解释还是有的困惑。假如一个对象已经被标记为垃圾了,其它线程怎么还会有机会引用它呢?就算通过stw,把它标记并回收了,那想引用它的线程重新恢复执行了会发生什么?

GC标记的是活着的(能够被引用到的)对象,剩下的是垃圾。如果没有STW,其他线程在垃圾回收过程中产生了垃圾(某对象不再被引用),那么会被漏掉。

总结

本文创作灵感来源于 极客时间 郑雨迪老师的《深入拆解 Java 虚拟机》课程,通过课后反思以及借鉴各位学友的发言总结,现整理出自己的知识架构,以便日后温故知新,查漏补缺。

关注本人公众号,第一时间获取最新文章发布,每日更新一篇技术文章。

a0e89fc342ea375f554a8865eeaaef0e.png



推荐阅读
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 深入探讨:Actor模型如何解决并发与分布式计算难题
    在现代软件开发中,高并发和分布式系统的设计面临着诸多挑战。本文基于Akka最新文档,详细探讨了Actor模型如何有效地解决这些挑战,并提供了对并发和分布式计算的新视角。 ... [详细]
  • 本文详细介绍了Android系统的四层架构,包括应用程序层、应用框架层、库与Android运行时层以及Linux内核层,并提供了如何关闭Android系统的步骤。 ... [详细]
  • 面试题总结_2019年全网最热门的123个Java并发面试题总结
    面试题总结_2019年全网最热门的123个Java并发面试题总结 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • 应用链时代,详解 Avalanche 与 Cosmos 的差异 ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 阿里巴巴终面技术挑战:如何利用 UDP 实现 TCP 功能?
    在阿里巴巴的技术面试中,技术总监曾提出一道关于如何利用 UDP 实现 TCP 功能的问题。当时回答得不够理想,因此事后进行了详细总结。通过与总监的进一步交流,了解到这是一道常见的阿里面试题。面试官的主要目的是考察应聘者对 UDP 和 TCP 在原理上的差异的理解,以及如何通过 UDP 实现类似 TCP 的可靠传输机制。 ... [详细]
  • 深入理解:AJAX学习指南
    本文详细探讨了AJAX的基本概念、工作原理及其在现代Web开发中的应用,旨在为初学者提供全面的学习资料。 ... [详细]
  • 探讨密码安全的重要性
    近期,多家知名网站如CSDN、人人网、多玩、开心网等的数据库相继被泄露,其中大量用户的账户密码因明文存储而暴露无遗。本文将探讨黑客获取密码的常见手段,网站如何安全存储用户信息,以及用户应如何保护自己的密码。 ... [详细]
  • 在Java开发中,保护代码安全是一个重要的课题。由于Java字节码容易被反编译,因此使用代码混淆工具如ProGuard变得尤为重要。本文将详细介绍如何使用ProGuard进行代码混淆,以及其基本原理和常见问题。 ... [详细]
  • 深入解析Java中的空指针异常及其预防策略
    空指针异常(NullPointerException,简称NPE)是Java编程中最常见的异常之一。尽管其成因显而易见,但开发人员往往容易忽视或未能及时采取措施。本文将详细介绍如何有效避免空指针异常,帮助开发者提升代码质量。 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 本文介绍了如何利用HTTP隧道技术在受限网络环境中绕过IDS和防火墙等安全设备,实现RDP端口的暴力破解攻击。文章详细描述了部署过程、攻击实施及流量分析,旨在提升网络安全意识。 ... [详细]
author-avatar
黑马@梦想
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有