目的:
本文描述了Sun公司的HotSpot
Java虚拟机的垃圾收集工作原理
。以便为更多Java爱好者在设计,开发以及部署时带来更多便利和益处。
摘要:
JVM
规范中要求任何实现JVM
的实现必须要提供一个能够回收未被使用内存的机制。这个机制就是垃圾回收(GC
-Garbage
Collection)。然而垃圾回收机制设计的好坏将直接影响依赖其运行的java应用的性能(包括处理能力,响应时间等)。在接下来的章节中将详细介绍SUN公司的Java虚拟机(其正式名称是Sun
HotSopt JVM
)中的垃圾回收机制。
分代垃圾回收
HotSpot
JVM
使用分代垃圾回收的方式。这种垃圾回收方式并不是HotSpot
JVM
的首创,而是人们在实践中发现存在下面的两条规律并在很早的时候就提出来了。即:
1
)大多数对象在创建后很短的时间内就会没有任何对象再使用它了,即未被其它对象引用。
2
)大多数一直被使用的对象(老对象)很少引用新创建的对象。
对于Java应用来说这两条规律始终是存在的,也有人根据这些规律称其为“弱分代”。因为将java对象分为“年轻”对象和“老”对象时并没有一个非常明确的指标而是由JVM
规范的实现者控制的(当然JVM
也可以提供参数让具体的开发者设定)。在HotSpot
JVM
中将分配到的内存堆(Heap)分为两个物理区域,一个是“年轻”区,另一个是“老”区。在这里我将“年轻”的一代叫做“新生代”,而对应的将“老”的一代对象叫做“老生代”。
l
新生代:绝大多数新创建的对象存放于此,这个区域一般来说比较小而且垃圾收集的频率也比较高。因为许多对象在创建后很快就会“死”去,在每次的“新生代”垃圾收集后能够“幸存”的对象非常的少。使用在“新生代”的这种垃圾收集叫做次要垃圾收集(Minor
Collection)。正是因为“新生代”的大小(较小,寻址时间很短)和其存放的对象的特点(寿命短,所以有很多垃圾,每次收集都能释放较大的内存空间)使得次要垃圾收集的效率非常高。见图1。
图
1
:分代垃圾回收
l
老生代:在“新生代”中生存了较长时间的对象将被提升为“老”对象并转移到“老生代”区。这个区域一般要大一些而且增长的速度相对于“新生代”要慢一些,所以负责“老生代”垃圾收集的主垃圾收集(Major
Collection)的执行频率与次要垃圾收集比要低很多。主垃圾收集发生在“老生代”中的对象占用的存储空间达到一定的量值的时候。见图1。
*
为方便起见,在下面的章节中将用次收集来替代“次要垃圾收集”,用主收集替代“主要垃圾收集”
。
为了使次收集的收集时间尽可能的短,HotSpot
JVM
使用了一种叫做卡表(Card
Table)的机制见图2,来避免在每次进行次收集的时候遍历整个“老生代”。
图2:HotSpot
中的卡表
卡表的机制是将“老生代”以512字节为单位进行划分,划分得到的每个区域叫做一个卡。每个卡在卡表中有占用一个一个字节的标识。java代码在执行的过程中JVM
一旦发现“老生代”的对象引用了或者释放了“新生代”中的对象,那么JVM
就要将与之对应的卡表中的状态置为相应的值。这样在次收集的时候只遍历被标记为“脏”的卡,以便知道哪些“新生代”的对象被引用中,是不可以进行回收的。
分代进行垃圾收集的好处是可以根据每个代的具体特点为其设定不同的垃圾收集算法。在新生代中往往使用速度较快的垃圾收集算法,因为次要收集的频率比较高。这种算法在内存的使用效率上没有优势,好在“新生代”的空间占整个JVM
内存堆比例较小,尚不能对性能构成大的问题。而内存使用效率高的算法往往用在“老生代”的垃圾收集上。因为“老生代”占据着JVM
堆的很大部分。虽然“老生代”中进行的主收集每次的收集时间相对于次收集要长好多,但是主收集在频率上要比次收集少很多,故对性能的影响也不大。正是这种新、“老生代”的相互补很好的平衡JVM
垃圾收集中的瓶颈。
新生代的组成
“新生代”又3个部分组成,见图3。一个Eden和两个生存区(
Survivor Space
),
图3:新生代组成
其中:
l
Eden
:绝大部分新创建的对象存放在此区域。为什么说绝大多数而不是所有的呢?原因是应用在创建一个非常大的对象的时候JVM
会直接将其分配在老生代而非新生代。在每次完成次收集的时候Eden区域总是空的。
l
存活区:顾名思义在垃圾收集过程中没有被当作垃圾收集的对象将放在次区域中。也就是说这个区域中的对象至少经历了一次次收集。存放存活区的对象在被“提升”到老生代前还有机会被收集。存活区有一对,他们中的一个始终保持为空,另一个用于存放存活下来的对象。
图4描述了次收集的收集过程,其中绿色部分是未被使用的对象
图4:一次次收集
(即垃圾)。从图中可以看到在Eden区的绿色部分将被收集而幸存下来的对象
(白色部分)将被移到没有被使用的存活区2。在存活区1中的绿色部分是也是不被使用的对象,这些对象也将被收集。而位于存活区1中的蓝色部分是尚被引用但
是还不够“老”的这些对象也将移到到存活区2。存活区1中剩余的部分就是被引用且已经够“老”的对象,他们将被移到老生代区。
在完成了一次次收集后(见图5),两个存活区就会交互角色。即存活区2中将存放存活对象,存活区1将不被使用。Eden区将会变的空空如也。同时由于有新对象移到了老生代,老生代的空间将被更多的对象占据。
图5:完成一次次收集后
垃圾收集器
Sun
的HotSpot
JVM
提供了3中不同的垃圾收集器。他们可以根据应用的实际情况有选择性的使用。下面将分别介绍。
串行收集器:
又叫做“标记-压缩”收集器。这种收集器在收集的时候要求JVM
停止执行应用。所以人们戏称这种收集模式为Stop-the-World(停止一切)模式。在完成收集后JVM
才继续执行应用(见图6)。
图6:串行收集
串行收集器首先将
“老生代”中的仍然存活的对象进行标记并将这些对象压缩到“老生代”空间的前端。这样“老生代”的后端将变成一个连续的空间,以便从“新生代”中足够老的
对象顺利的“提升”到“老生代”中(见图7,红色部分为垃圾对象)。对于大多数不要求有非常迅速响应(例如几秒钟)的场合,例如客户端程序,这种收集器还
是能够胜任的。
图7:“老生代”的一次压缩
并行收集器:
在
目前实际的应用中多数的java程序都运行在具有很大物理内存和多个CPU的服务器上。在比较理想的情况下垃圾收集应该能够有效利用所有的CPU,而不是
只用其中的一个且其他的CPU都处于空闲状态。为避免过多的垃圾收集以便提高系统的吞吐量(即处理能力),在服务器模式的环境下Sun的HotSopt
JVM
使用
并行收集器进行垃圾回收。因为这种垃圾回收器的一个主要目标是提高吞吐量,所以也叫做吞吐量型的收集器。并行收集器的工作方式是在次收集(对应于“新生
代”)中使用所有的CPU进行并行收集,在主收集(对应于“老生代”)中采用串行收集器(见图8)。虽然与串行收集器相比较主收集没有显著的改善(因为两
者在“老生代”中都使用了相同的串行收集器),但是在次收集部分的效率得以大幅度的提高。进而提高的系统的吞吐量。
图8:并行收集
同步收集器(
Mostly-Concurrent
Collector
)
:
对
于某些的应用程序来说响应速度要远比吞吐量重要。同时收集器就是为低延时而设计的一种收集器。在已经介绍的Stop-the-World(停止一切)的收
集模式中,当垃圾收集没有结束前对于外部的请求是不会进行响应的,直到收集完毕应用才会继续响应请求。这对于次搜集来说一般来说停顿时间不是很长(因为次
收集往往需要很短的时间),但对于主收集来说,即使不是很频繁也会导致应用较长时间的停顿,尤其是在JVM
堆分配的比较大的时候就更明显了。为了解决这种情况Sun
JVM
引入了同步收集器的方式。这种方式也叫做同步标记-清楚(CMS)或者还可以叫做“低延迟”收集器。图9展示了其工作原理
。
图9:同步收集器
同步收集器以一个短
暂的停顿开始,在这个短暂的停顿中将对那些能够迅速确定不是垃圾的对象进行标记。紧接着将进入同步标记阶段,在这个阶段中同步收集器对被使用的对象进一步
进行标记,而应用也同时运行。应用在运行的过程中可能改变了对某些对象的引用,这使得同步标记阶段中并不能保证所有的被引用对象进行了标记,也导致了必须
需要进行的第三个阶段-“再标记”。在再标记阶段中将会使应用进入第二个暂停,利用这个暂停时间同步收集器将完成对所有对象的标记。可以看出在再标记的过
程中使用了并行的方式,所以这部分标记的对象的数量要比在初始阶段中标记完成的多。在最后一个阶段同步收集器将会把前几个阶段中标记出来的“老生代”中的
垃圾对象进行清除。但是不会将被引用的对象放在一个连续的空间中(见图10,橙色为垃圾对象,绿色为收集后的空闲空间)。可以看出“老生代”中的可用空间
并不是连续的,这个会导致将为提升到“老生代”的对象分配空间时需要工多的时间和资源。
图10:“老生代”中的同步清除
与串行收集器和并行收集器相比较同步收集器会有下面几个特点。
1)
要求分配到的堆大;
2
)对不连续空间的使用效率低;
3
)在某些情况下能够显著缩短主收集使应用停顿的时间。
附录A:参考文献
JVM
Specification
第二版
http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html
分享到:
相关推荐
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
# 基于Qt框架的智能家居管理系统 ## 项目简介 本项目是一个基于Qt框架开发的智能家居管理系统,旨在提供一个集成的平台来监控和管理家庭环境中的各种传感器数据,如温度、湿度、烟雾状态、红外状态等。系统通过图形界面实时展示数据,并提供警报功能以应对异常情况。 ## 项目的主要特性和功能 1. 实时数据监控通过Qt和Qwt库创建的曲线图,实时显示温度和湿度数据。 2. 多传感器支持支持温度、湿度、烟雾、红外等多种传感器的监控。 3. 警报系统当传感器数据超过设定阈值时,系统会触发警报,并通过界面显示警告信息。 4. 用户交互提供滑动条和复选框,允许用户调整警报阈值或关闭警报。 5. 网络通信通过TCP套接字与服务器通信,获取和发送传感器数据及网络拓扑信息。 6. 蓝牙数据读取支持通过蓝牙读取传感器数据并更新界面显示。 ## 安装使用步骤 1. 环境准备 确保已安装Qt开发环境。 安装Qwt库以支持曲线图功能。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
基于springboot高性能计算中心的高性能集群共享平台源码数据库文档.zip
# 基于JavaFX的图片管理系统 ## 项目简介 本项目是一个基于JavaFX的图片管理系统,旨在提供一个用户友好的界面来管理和浏览图片。系统支持图片的预览、重命名、删除、复制、粘贴等操作,并提供了多种排序和展示方式。 ## 项目的主要特性和功能 1. 预览窗口 目录树展示 缩略图预览 单选、多选(Ctrl+左键)、框选功能 图片信息显示(如文件名、大小、最后修改时间等) 2. 右键菜单 复制粘贴图片 单选和多选重命名 删除图片 3. 展示窗口 图片放大缩小 左右切换图片 幻灯片播放功能 4. 排序功能 按文件名排序 按文件大小排序 按最后修改时间排序 5. 其他功能 图片信息封装(ImageBean) 文件树节点管理(FileTreeItem)
# 基于Windows窗体的披萨店厨房管理系统 ## 项目简介 这是一个基于Windows窗体的应用程序,主要用于披萨店的厨房管理。该系统通过WebSocket与服务器进行实时通信,显示从服务器接收到的订单信息。用户界面简洁明了,易于操作。 ## 项目的主要特性和功能 1. 实时通信: 通过WebSocket与服务器进行实时数据交换,获取订单信息。 2. 订单显示: 在窗体上实时显示订单信息,包括订单号和菜品等。 3. 界面简洁: 用户界面设计简洁,易于操作。 4. 定时刷新: 定时器用于定时从服务器获取消息,确保数据的实时性。 5. 错误处理: 在连接过程中遇到技术问题时会显示错误消息框。 6. 退出功能: 提供退出按钮,点击后程序会退出。 ## 安装和使用步骤 1. 下载项目源码文件: 从相关仓库或网站下载此项目的源码文件。 2. 准备开发环境: 确保你的开发环境已经安装了必要的软件和工具,如Visual Studio等。
基于springboot高校创新创业课程体系源码数据库文档.zip
基于springboot汽车美容与保养网站源码数据库文档.zip
基于springboot校友录管理系统源码数据库文档.zip
Cocos2d-x教程视频使用Eclipse在Ubuntu下搭建Cocos2d-x 3集成开发环境提取方式是百度网盘分享地址
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
基于springboot服装生产管理信息系统源码数据库文档.zip
# 基于Spring Boot和Redis的高并发秒杀系统 ## 项目简介 本项目是一个基于Spring Boot框架开发的高并发限时抢购秒杀系统。系统实现了基本的登录、查看商品列表、秒杀、下单等功能,并针对高并发场景进行了优化,包括系统缓存、降级和限流等措施。通过Redis、RabbitMQ等中间件技术,确保系统在高并发情况下的稳定性和性能。 ## 项目的主要特性和功能 ### 核心功能 用户登录用户可以通过手机号和密码进行登录,系统支持两次MD5加密确保密码安全。 商品列表展示用户可以查看所有商品的列表,包括商品的详细信息、库存数量、秒杀价格等。 商品详情展示用户可以查看单个商品的详细信息,包括秒杀状态和剩余时间。 秒杀下单用户可以参与秒杀活动,系统通过本地标记、Redis预处理、RabbitMQ异步下单等技术确保高并发下的系统稳定。 订单详情用户可以查看自己的订单详情,包括订单状态、商品信息等。 ### 技术优化
基于springboot校园论坛系统源码数据库文档.zip
飞利浦CT机自动推送配置
本教程介绍了 PHP 的基础语法、函数与面向对象编程、文件操作、以及与 MySQL 的交互。通过实例与练习,帮助您快速入门 PHP 开发,为动态网站和 Web 应用打下坚实基础。
# 基于Android的玩具租赁系统 ## 项目简介 本项目是一个基于Android平台的玩具租赁系统,旨在为用户提供一个便捷的玩具租赁服务。系统涵盖了用户注册、登录、玩具浏览、租赁、个人信息管理等功能,通过前后端分离的架构实现。 ## 项目的主要特性和功能 1. 用户管理 用户注册与登录支持通过昵称、手机号等多种方式进行注册和登录。 找回密码用户可以通过手机验证码找回密码。 个人信息管理用户可以修改个人信息,包括姓名、密码等。 2. 玩具租赁 玩具浏览用户可以浏览不同分类的玩具,查看玩具详情。 租赁功能用户可以选择玩具进行租赁,并查看租赁订单。 3. 搜索与推荐 搜索功能用户可以通过关键词搜索玩具。 推荐系统根据用户的历史行为推荐相关玩具。 4. 测试与集成 单元测试确保基础功能的正确性。 集成测试测试Spring Boot应用的上下文加载情况。
6个免费的所见即所得Markdown桌面编辑器的实用指南,用于在Windows平台上编写GitHub Readme.md文件(截至2024年9月)。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
# 基于Arduino IDE和Flutter的电动汽车充电监控系统 ## 一、项目简介 这是一个电动汽车充电监控项目,旨在通过Arduino IDE创建一个HTTP Web服务器,结合ESP32芯片、电源管理集成电路(IC)、电流和电压传感器,实现对电动汽车充电过程的实时监控和管理。同时,该项目还包括一个基于Flutter开发的移动应用,方便用户通过移动设备查看和控制充电过程。 ## 二、项目的主要特性和功能 1. HTTP Web服务器通过Arduino IDE创建HTTP Web服务器,实现与ESP32芯片的通信。 2. ESP32芯片连接WiFi,并作为中间设备连接电源管理集成电路(IC)、电流和电压传感器。 3. 远程监控与控制用户可以通过移动设备访问特定的网页,输入充电瓦数并提交,实现远程监控和控制充电过程。 4. Flutter应用项目中的Flutter应用提供了用户友好的界面,方便用户查看充电状态、调整充电参数等。