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关键字持有的对象。

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

相关推荐
七夜zippoe2 小时前
应用安全实践(一):常见Web漏洞(OWASP Top 10)与防护
java·前端·网络·安全·owasp
Zzj_tju2 小时前
Java 从入门到精通(十一):异常处理与自定义异常,程序报错时到底该怎么处理?
java·开发语言
aP8PfmxS22 小时前
Lab3-page tables && MIT6.1810操作系统工程【持续更新】
java·linux·jvm
深蓝海拓2 小时前
S7-1500学习笔记:Array数据类型
笔记·学习·plc
无籽西瓜a2 小时前
【西瓜带你学设计模式 | 第十二期 - 装饰器模式】装饰器模式 —— 动态叠加功能实现、优缺点与适用场景
java·后端·设计模式·软件工程·装饰器模式
吴声子夜歌2 小时前
Node.js——zlib压缩模块
java·spring·node.js
海参崴-2 小时前
深入剖析C语言结构体存储规则:内存对齐原理与实战详解
java·c语言·开发语言
南山乐只2 小时前
Java并发工具:synchronized演进,从JDK 1.6 锁升级到 JDK 24 重构
java·开发语言·后端·职场和发展
无籽西瓜a2 小时前
【西瓜带你学设计模式 | 第十三期 - 组合模式】组合模式 —— 树形结构统一处理实现、优缺点与适用场景
java·后端·设计模式·组合模式·软件工程