网站首页 > java教程 正文
作为Java开发人员,我们对垃圾收集的概念并不陌生。我们的应用程序一直在产生垃圾,这些垃圾被CMS、G1、Azul C4 和其他类型的收集器精心清理。基本上,我们的应用程序生来就是为了给这个世界带来价值,但是,没有什么是完美的——包括我们在Java堆中留下垃圾的应用程序。
然而,故事并没有以Java堆结束。事实上,它只是从那里开始。让我们以一个基本的Java应用程序为例,该应用程序使用PostgreSQL等关系数据库和固态驱动器 (SSD) 作为存储设备。从这里,我们将探索我们的应用程序如何在Java运行时边界之外生成垃圾。
用Dead Tuples填充 PostgreSQL
当你的Java应用程序对 PostgreSQL数据库执行DELETE或UPDATE语句时,不会立即删除已删除的记录,也不会在其位置更新现有记录。相反,删除的记录被标记为Dead Tuples并将保留在存储中。更新的记录实际上是PostgreSQL通过复制先前版本的记录并更新请求的列来插入的全新记录。该更新记录的先前版本被视为已删除,并且与DELETE操作一样,被标记Dead Tuples。
数据库引擎在其存储中保留旧版本的已删除和更新记录是有充分理由的。对于初学者,你的应用程序可以针对PostgreSQL并行运行一堆事务。其中一些交易确实比其他交易更早开始。但是,如果一个事务删除了一条记录,而该记录可能对一些较早开始的事务仍然感兴趣,那么该记录需要保存在数据库中(至少直到所有较早开始的事务完成的时间点)。这就是 PostgreSQL实现MVCC(多版本并发协议)的方式。
很明显,PostgreSQL不能也不想永远保留Dead Tuples。这就是为什么数据库有自己的垃圾收集过程,称为清理。有两种类型的VACUUM——普通的和完整的。普通的VACUUM与你的应用程序工作负载并行工作,不会阻止你的查询。这种类型的清理将Dead Tuples占用的空间标记为空闲,使其可用于你的应用稍后将添加到同一个表中的新数据。普通的VACUUM不会将空间返回给操作系统,以便它可以被其他表或 第三方应用程序重用(在某些极端情况下,当页面仅包含Dead Tuples并且页面位于表的末尾时)。
相比之下,完整的VACUUM确实将可用空间回收给操作系统,但它会阻止应用程序工作负载。你可以将其视为Java的“stop-the-world”垃圾收集暂停。只有在PostgreSQL中,这样的暂停才能持续数小时(或数天)。因此,数据库管理员尽最大努力防止完全VACUUM发生。
在SSD中生成陈旧数据
如果你认为垃圾收集只是为了软件,那就错了!一些硬件设备也需要执行垃圾收集例程。SSD一直在做垃圾收集!
每当你的Java应用程序删除或更新磁盘上的任何数据时——通过上面讨论的PostgreSQL或直接通过Java文件 API——应用程序就会在SSD上生成垃圾。
SSD将数据存储在页面中(通常大小在4KB和16KB之间),后者按块分组。虽然你的数据可以在页面级别写入或读取,但陈旧(已删除)的数据只能在块级别擦除。擦除需要比读/写操作更多的电压,并且很难在不影响相邻单元的情况下将电压定位在页面级别。
因此,如果你的Java应用程序更新了文件,那么事实上,更新的段将被写入可能位于不同块中的空页面。带有旧数据的段将被标记为过时,稍后将被垃圾收集。首先,SSD中的垃圾收集器遍历具有陈旧数据的页面块,并将好的数据移动到其他块(类似于Java的G1收集器中的压缩阶段)。其次,收集器擦除只剩下陈旧数据的块,并使这些块可用于未来的数据。
好奇SSD制造商如何防止或尽量减少“stop-the-world”暂停的次数? 有一个SSD过度配置的概念,即每台设备都有一个额外的空间供你的应用程序使用。该空间是一种安全缓冲区,允许应用程序继续写入或修改数据,同时垃圾收集器同时擦除陈旧数据。
总结
严肃地说,垃圾收集是一种广泛使用的技术,其使用范围远远超出Java生态系统。如果实施得当,垃圾收集可以在不影响性能的情况下简化软件和硬件的架构。Java、PostgreSQL和SSD都是成功利用gar的产品的好例子。
猜你喜欢
- 2024-09-30 SQL SERVER 清理日志文件的方法(sql server怎么清除日志)
- 2024-09-30 如何使用 Java 在 PDF 文档中添加、删除或旋转页面
- 2024-09-30 夯实基础:完全理解掌握Java文件类File
- 2024-09-30 Java基础——IO流(10)(java基础)
- 2024-09-30 Java编程思想:清除一收尾和垃圾收集
- 2024-09-30 Java教程Java 文件 IO 操作(java io写文件)
- 2024-09-30 近2万字详解JAVA NIO2文件操作,过瘾
- 2024-09-30 JAVA运维必备——linux的基本常见命令,也是“装逼”命令
- 2024-09-30 Java中常用IO流之文件流的基本使用姿势
- 2024-09-30 Java平台的海量小文件分布式文件系统BRFS-全套源码+文档
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)