JVM系列-分代收集垃圾回收
Java自动垃圾回收(Automatic Garbage Collection)是自动回收堆上不再使用的内存,new的对象在程序中没有引用指向它,就会被回收。回收的实现很多,有Reference Counting Collector/Tracing Collector/Compacting Collector/Coping Collector/Generational Collector/Adaptive Collector。本文记录的是HotSpot Java VM采用的Generational Collector(分代收集器)。
为什么分代?
下图是随着时间的推移,经历垃圾回收后存活下的数据大小情况。可以看出大部分对象存活期很短,随着时间的推移越来越少的对象存活下来。因此,可以针对不同的堆内存采取不同的回收频率和方法,以提高JVM性能。
堆内存分代概念
下图是Generation GC对内存结构的划分:
Eden:用于new对象时分配的内存空间,大部分初始new的对象位于该空间
Survivor Space:在eden中经历垃圾回收后,存活下来的对象被存储在该空间
tenured Space:在survivor space中存在了一段时间的对象会被挪到该空间
Permanent Space:JVM使用的元数据,如classloader加载的class/method定义(反射后的数据)。
Code Cache:用于编译和存储原代码
其中Permanent Space和Code Cache不属于generation collector回收范围。但是当Permanent Space已用完,且需要加载新class时,会触发Full GC对Permanent进行回收,卸载(清除)那些不再被需要的class。
如何分代收集
new对象会最初分配在eden中,当eden满时触发minor garbage collection。
Minor GC(又称作Young GC)针对young generation:
- eden/S0中存活的对象被复制到S1中,eden/S0被清空
- 每次minor gc,存活对象的age会加1,当age超过阈值后,对象被存到old generation中。
- S0和S1是相对的,第一次Minor GC时S0/S1都是空的,从eden往S0复制,第二次minor gc就是从eden/S0往S1复制,下一次是eden/S1到S0,以后依次类推。
Minor GC采用的是复制收集,young generation中的对象大部分是不再使用,所以复制存活下来的对象到新空间,旧空间整体回收,这样的一个过程会更快。
随着Minor GC的发生,被promoted到old generation的对象越来越多,当old generation满时就触发了major garbage collection。Major GC(又称作Old GC)针对old generation,采取marking-deletion-compact(标记-清除-压缩内存)的方法。(补:压缩内存,就是把活着的对象放在一块,省出连续的空闲内存,便于分配)
通常Major GC又被认为是Full GC,因为Major GC发生时会伴随着Minor GC:一次Minor GC将存活对象放到old generation时导致old generation满了,从而导致Major GC。这一段时间整个堆内存表现出的现象是都进行了garbage collection。
建议
Minor/Major GC都是Stop the World事件,应用程序会停止执行,直到GC完成。Major GC发生时,整个堆内存都受到了影响,持续时间长。
所以应该尽量避免或减少Major GC(减少被放到old generation的对象);尽量最大化堆内存。
实际使用
在启动java程序时通过设置相关命令参数调节垃圾回收的方法、阈值或频率来优化GC对程序的影响,常用命令如下:
| Switch | Description |
-Xms |
Sets the initial heap size for when the JVM starts. |
-Xmx |
Sets the maximum heap size. |
-Xmn |
Sets the size of the Young Generation. |
| -XX:PermSize | Sets the starting size of the Permanent Generation. |
| -XX:MaxPermSize | Sets the maximum size of the Permanent Generation |
GC的串并行
串行GC在JavaSE 5/6上是默认方式,常用于对暂停时间要求不高、客户端类型的应用程序上,也适用于应用程序的数目比CPU多的情况,这样GC时JVM之间的影响小。MB级别的堆内存进行Full GC时只需要几秒。设置的命令是-XX:+UseSerialGC。
并行GC使用多线程进行Minor GC,线程数默认与CPU数相等。设置的相关命令是-XX:+UseParallelGC和-XX:ParallelGCThreads=<desired number>(指定线程数)。-XX:+UseParallelOldGC会设置Minor GC和Major GC都采用多线程。
CMS
并发标记清除收集器(Concurrent Mark Sweep)用于old generation的垃圾回收,它尽力减少程序的暂停时间,GC工作和应用程序的线程并发执行。它不做compact(压缩)堆内存,省去了内存的拷贝和移动。当内存碎片过多无法满足分配时,就直接重新分配一块更大的堆内存。CMS适用于webserver或者查询类的应用。
相关命令:-XX:+UseConcMarkSweepGC和-XX:ParallelCMSThreads=<n>(设置并行线程数)
G1 Garbage Collector
G1回收器在Java7中被引进,希望能取代CMS,它主要是并发、增量式的compact内存,以取得低暂停。相关命令:-XX:+UseG1GC
一个实例
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseParallelOldGC -jar Java2demo.jar
参考:http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
JVM系列-分代收集垃圾回收的更多相关文章
- JVM的永久代会发生垃圾回收吗?
垃圾回收不会发生在永久代中.当永久代满或者超过临界值时,就会触发完全垃圾回收(Full GC).如果仔细查看垃圾收集器中的输出信息,就会发现永久代也是被回收的.这就是正确的永久代大小对避免Full G ...
- JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集
(转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...
- JVM虚拟机学习一:垃圾回收算法总结
1.java虚拟机中涉及到的数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型. 基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了某 ...
- 推荐收藏系列:一文理解JVM虚拟机(内存、垃圾回收、性能优化)解决面试中遇到问题(图解版)
欢迎一起学习 <提升能力,涨薪可待篇> <面试知识,工作可待篇 > <实战演练,拒绝996篇 > 欢迎关注我博客 也欢迎关注公 众 号[Ccww笔记],原创技术文章 ...
- JVM之GC算法、垃圾收集算法——标记-清除算法、复制算法、标记-整理算法、分代收集算法
标记-清除算法 此垃圾收集算法分为“标记”和“清除”两个阶段: 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记对象,它的标记过程前面已经说过——如何判断对象是否存活/死去 死去的对象就会 ...
- JVM垃圾收集算法——分代收集算法
分代收集算法(Generational Collection): 当前商业虚拟机的垃圾收集都采用"分代收集算法". 这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分 ...
- JVM的内存分配与垃圾回收策略
自动内存管理机制主要解决了两个问题:给对象分配内存以及回收分配给对象的内存. >>垃圾回收的区域 前面的笔记中整理过虚拟机运行数据区,再看一下这个区域: 注意在这个Runtime Data ...
- Java虚拟机:JVM内存分代策略
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! Java虚拟机根据对象存活的周期不同,把堆内存划分为几块,一般分为新生代.老年代和永久代(对HotSpot虚拟机而言),这就是JVM的内存 ...
- jvm学习笔记一(垃圾回收算法)
一:垃圾回收机制的原因 java中,当没有对象引用指向原先分配给某个对象的内存时候,该内存就成为了垃圾.JVM的一个系统级线程会自动释放该内存块.垃圾回收意味着程序不再需要的对象是"无用信息 ...
随机推荐
- android应用程序第一次启动时显示引导界面
市面上好多优秀的应用(举例新浪微博.UC浏览器)都采用了欢迎页面与使用向导的方式给用户带来了良好的用户体验. 一般来说用户第一次安装应用或者安装了新版本后第一次进入应用都会显示成 欢迎页面-使用向导- ...
- BZOJ 1047 二维单调队列
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1047 题意:见中文题面 思路:该题是求二维的子矩阵的最大值与最小值的差值尽量小.所以可以考 ...
- Ubuntu14.04下安装docker
http://www.cnblogs.com/xiaoluosun/p/5520510.html
- three.js立方体
<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - ge ...
- 2016-2-10 tomcat基础学习
安装tomcat服务器(1)配置 JAVA_HOME指向你的jdk主目录 也可以在startup.bat文件中设置JAVA_HOME环境变量. 首次使用JAVA_HOME前设置即可.set JAVA_ ...
- 三星首次更新Gear VR虚拟现实浏览器Samsung Internet
通过VR浏览网页不是问题,不过你需要一个专门的VR浏览器,而GearVR的虚拟现实应用名为"Samsung Internet for Gear VR".继去年12月份上线后,迎来了 ...
- bzoj1503郁闷的出(cheng)纳(xu)员
好痛苦,,,WA了不知道多少遍 错的服了,,, 如果某员工的初始工资低于工资下界,他将立刻离开公司 我也不知道是我语文有问题还是题目有毒,反正这个东西好像不应该算在离开公司的总人数的答案里... 让我 ...
- 提交数据url太长导致提交失败
使用了dojo开发.在datagrid过滤的时候.为了让过滤好处理,直接设置为完全二叉树的方式来存查询条件.但是在提交数据的时候,默认是get?url的方式.结果导致条件选择一两个,url会特别长.然 ...
- Matlab读取数据中出现的问题
在运行Matlab读取一段数据并做处理的时候,常常会提示服务器错误,但是等待一会再次运行就会成功运行. 代码如下: clc; clear all; [~,~,rawdata] = xlsread('进 ...
- eclipse 项目显示红叉
***修改eclipse 代码提示级别1.单个项目修改项目上右键-->properties-->java compiler-->building-->enable projec ...