JVM学习-基础篇-垃圾回收

垃圾回收

在C/C++这类没有自动垃圾回收机制的语言中,一个对象如果不再使用,需要手动释放,否则就会出现内存泄漏。内存泄漏指的是不再使用的对象在系统中未回收,内存泄漏的积累可能会导致内存溢出。
Java中为了简化对象的释放,引入了自动的垃圾回收(Garbage Collection简称GC)机制。通过垃圾回收器来堆不再使用的对象完成自动的回收,垃圾回收器主要负责对堆上内存进行回收。

垃圾回收器如果发现某个对象不再使用,就可以回收该对象。

  • 自动垃圾回收,自动根据对象是否使用由虚拟机来回收对象

    • 优点:降低程序员实现难度,降低对象回收bug 的可能性

    • 缺点:程序员无法控制内存回收的及时性

  • 手动垃圾回收,由程序员编程实现对象的删除

    • 优点:回收及时性高,由程序员把控回收的时机

    • 缺点:编写不当容易出现悬空指针、重复释放、内存泄漏等问题

首先线程不共享的部分,都是伴随着线程的创建而创建,线程的销毁而销毁。而方法的栈帧在执行完方法之后就会自动弹出栈并释放掉对应的内存。所以这一部分不需要垃圾回收器负责。

方法区的回收

方法区中能回收的内容主要就是不再使用的类。

判定一个类可以被卸载。需要同时满足下面三个条件:

1、此类所有实例对象都已经被回收,在堆中不存在任何该类的实例对象以及子类对象。

2、加载该类的类加载器已经被回收。

3、该类对应的 java.lang.Class 对象没有在任何地方被引用。

如何判断对象可以回收

垃圾回收器要回收对象的第一步就是判断哪些对象可以回收。Java中的对象是否能被回收,是根据对象是否被引用来决定的。如果对象被引用了,说明该对象还在使用,不允许被回收。

第一行代码执行之后,堆上创建了Demo类的实例对象,同时栈上保存局部变量引用堆上的对象。

第二行代码执行之后,局部变量对堆上的对象引用去掉,那么堆上的对象就可以被回收了。

一个更复杂的案例:

这个案例中,如果要让对象a和b回收,必须将局部变量到堆上的引用去除。

那么问题来了,A和B互相之间的引用需要去除吗?答案是不需要,因为局部变量都没引用这两个对象了,在代码中已经无法访问这两个对象,即便他们之间互相有引用关系,也不影响对象的回收。

判断对象是否可以回收,主要有两种方式:引用计数法和可达性分析法。

引用计数法

引用计数法会为每个对象维护一个引用计数器,当对象被引用时加1,取消引用时减1。

比如下图中,对象 A 的计数器初始化为0,局部变量 a1 对它引用之后,计数器加 1 就变成了 1。同样 A 对 B 产生了引用,B的计数器也是1。

引用计数器的优点是实现简单,缺点主要有两点:

  • 每次引用和取消引用都需要维护计数器,对系统性能会有一定的影响。

  • 存在循环引用问题,所谓循环引用就是当A引用B,B同时引用A 时会出现对象无法回收的问题。

下图,由于A 和 B之间存在互相引用,所以计数器都为1,两个对象都不能被回收。但是由于没有局部变量对这两个代码产生引用,代码中已经无法访问到这两个对象,理应可以被回收。

可达性分析法

Java使用的是可达性分析算法来判断对象是否可以被回收。可达性分析将对象分为两类:垃圾回收的根对象(GC Root)和普通对象,对象与对象之间存在引用关系。

下图中A到B再到C和D,形成了一个引用链,可达性分析算法指的是如果从某个到 GC Root 对象是可达的,对象就不可被回收。

哪些对象被称之为GC Root对象呢?

  • 线程Thread对象,引用线程栈帧中的方法参数、局部变量等。

  • 系统类加载器加载的java.lang.Class对象,引用类中的静态变量。

  • 监视器对象,用来保存同步锁synchronized关键字持有的对象。

  • 本地方法调用时使用的全局对象。

相关推荐
Dicky-_-zhang5 小时前
消息队列Kafka/RocketMQ选型与高可用架构:从单体到100万TPS的演进
java·jvm
晨曦中的暮雨5 小时前
4.15腾讯 CSIG云服务产线 一面
java·开发语言
2301_781571425 小时前
Golang格式化输出占位符都有什么_Golang fmt占位符教程【通俗】
jvm·数据库·python
fake_ss1985 小时前
AI时代学习全栈项目开发的新范式
java·人工智能·学习·架构·个人开发·学习方法
茉莉玫瑰花茶6 小时前
工作流的常见模式 [ 1 ]
java·服务器·前端
未若君雅裁6 小时前
Spring AOP、日志切面与声明式事务原理
java·后端·spring
Upsy-Daisy6 小时前
AI Agent 项目学习笔记(二):Spring AI 与 ChatClient 主链路解析
人工智能·笔记·学习
No8g攻城狮7 小时前
【人大金仓】wsl2+ubuntu22.04安装人大金仓数据库V9
java·数据库·spring boot·非关系型数据库
xiaoerbuyu12337 小时前
开源Java 邮箱 基于SpringBoot+Vue前后端分离的电子邮件
java·开发语言