DevNotes-Java应用程序是如何在堆之外丢弃垃圾?-《Java笔记》

admin 2025-10-19 02:53:57 编程 来源:ZONE.CI 全球网 0 阅读模式

Java作为 Java 开发人员,对垃圾收集的概念并不陌生。应用程序一直在生成垃圾,这些垃圾会被 CMS、G1、Azul C4 和其他类型的收集器给仔细清理掉。基本上,应用程序生来就是为这个世界带来价值的。但是,没有什么是完美的——包括在 Java 堆中留下垃圾的应用程序。然而,这并没有结束于 Java 堆。事实上,这只是开始。下面将基于一个基本的 Java 应用程序为例,使用了关系数据库(如 PostgreSQL)和固态硬盘(SSD)作为存储设备。这里将探索应用程序是如何在超出 Java 运行的界限时生成垃圾。

用死亡元组填充关系数据库

当 Java 应用程序对 PostgreSQL 数据库执行 DELETE 或 UPDATE 语句时,删除的记录不会立即删除,现有的记录也不会更新。相反,被删除的记录会被标记为死亡元组,并将其保留在存储中。实际上,更新后的记录是一个全新的记录, PostgreSQL 通过赋值前一个版本的记录并更新请求的列来插入。该更新记录的前一个版本会被认为已删除,并且和 DELETE 操作一样,被标记为死亡元组。数据库引擎在其存储中保存已删除和更新记录的旧版本是有原因的。对于初学者而言,应用程序可以在 PostgreSQL 上并行运行一堆事务。其中一些事务确实比其他事务开始得更早。但是,如果一个事务删除了一条记录,而这条记录对于之前启动的一些事务来说仍然是有意义的,那么需要将该记录保存在数据库中(至少在所有较早开始的事务完成之前)。这就是 PostgreSQL 如何实现 MVCC(多版本并发协议)的。很显然,PostgreSQL 不能也不想永远保存死亡元组。这就是为什么数据库有自己的垃圾收集过程,称之为 VACUUM(真空吸尘器)。VACUUM 有两种类型——普通的和完整地。普通的 VACUUM 与应用程序负载并行工作,不会阻塞查询。这种类型的 VACUUM 会将死亡元组占用的空间标记为空闲空间,使其可用于应用程序稍后将添加到同一个表中的新数据。普通的 VACUUM 不会将空间返回给操作系统,这样它就可以被其他表或第三方应用程序重用(除非在某些极端情况下,一个页只包含死亡元组,并且该页位于表的末尾)。Java 应用程序是如何在堆之外丢弃垃圾? - 图1相比之下,完整的 VACUUM 会将空闲空间回收给操作系统,但是它会阻塞应用程序的工作负载。可以将其视为 Java 的 STW(Stop The World) 垃圾收集暂停。只有在 PostgreSQL 中,这样的暂停可以持续数小时(或数天)。因此,数据库管理员尽最大努力防止发生完全的真空。

在固态硬盘上生成过期数据

如果认为垃圾收集只适用于软件,那么将会发生许多意外!一些硬件设备也需要执行垃圾收集例程。SSD 一直在进行垃圾收集!每当Java 应用程序删除或更新磁盘上的任何数据(通过上面讨论的 PostgreSQL 或直接通过 Java 文件 API),然后应用程序会在 SSD 上生成垃圾。SSD 是以页面的形式存储数据(通常大小在 4KB 到 16KB 之间),后者以块的形式分组。虽然可以在页面级写入或读取数据,但过时的(已删除的)数据只能在块级删除。与读/写操作相比,删除操作需要更多的电压,并且很难在不影响相邻单元的情况下在页面级指定电压。所以,如果Java应用更新了一个文件,那么,实际上,一个更新的段将被写入一个空页,可能在不同的块中。带有旧数据的段将被标记为陈旧的,稍后将被垃圾收集。首先,ssd中的垃圾收集器遍历带有过期数据的页面块,并将好的数据移动到其他块(类似于Java G1收集器中的压缩阶段)。其次,收集器擦除只剩下过时数据的块,并使这些块对未来的数据可用。Java 应用程序是如何在堆之外丢弃垃圾? - 图2

总结

总的来说,垃圾收集是一种广泛使用的技术,其使用范围远远超出Java生态系统。如果实现得当,垃圾收集可以简化软件和硬件的架构,而不会影响性能。Java、PostgreSQL 和 ssd 都是很好的例子,它们成功地利用了垃圾收集,并且仍然是同类产品中的佼佼者。

以太坊cppgolang区别 编程

以太坊cppgolang区别

以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
progolang 编程

progolang

Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
golangn个发送者 编程

golangn个发送者

Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
golang技能图谱 编程

golang技能图谱

从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
评论:0   参与:  10