JVM & GC 笔记
0. 说明
转载并修改自JVM
1. JVM
1.1 什么是JVM
JVM为Java虚拟机(Java Virtual Machine)
Runtime data area,运行时数据区。
包含5个区域,分别为:
method area (方法区)
heap (堆)
java stack (java栈)
native method stack (本地方法栈)
program counter register。 (程序计数器)
图示如下:
1.2 method area(方法区)
用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译后的代码等信息。
方法区是线程间共享的,当两个线程同时需要加载一个类型时,只有一个类会请求ClassLoader加载,另一个线程会等待。
1.3 heap(堆)
虚拟机中用于存放对象与数组实例的地方,垃圾回收的主要区域就是这里(还可能有方法区)。
如果垃圾收集算法采用按代收集(目前大都是这样),这部分还可以细分为新生代和老年代。新生代又可能分为Eden区,From Survivor区和To Survivor区,主要是为了垃圾回收。所有的线程共享Java堆,在这里还可以划分线程私有的缓冲区(Thread Local Allocation Buffer,TLAB)。
1.4 java stack(java栈)
虚拟机栈也是线程私有的,每创建一个线程,虚拟机就会为这个线程创建一个虚拟机栈。
虚拟机栈表示Java方法执行的内存模型,每调用一个方法,就会生成一个栈帧(Stack Frame)用于存储方法的本地变量表、操作栈、方法出口等信息,当这个方法执行完后,就会弹出相应的栈帧。
栈帧分为三部分:局部变量区(Local Variables)、操作数栈(Operand Stack)和帧数据区(Frame Data)。
如果请求的栈的深度过大,虚拟机可能会抛出StackOverflowError异常,如果虚拟机的实现中允许虚拟机栈动态扩展,当内存不足以扩展栈的时候,会抛出OutOfMemoryError异常。
1.5 native method stack(本地方法栈)
与虚拟机栈类似,只是是执行本地方法时使用的。
1.6 program counter register。(程序计数器)
类似于PC寄存器,是一块较小的内存区域,通过程序计数器中的值寻找要执行的指令的字节码,由于多线程间切换时要恢复每一个线程的当前执行位置,所以每个线程都有自己的程序计算器。这一个区域不会有OutOfMemeryError。当执行Java方法时,这里存储的执行的指令的地址,如果执行的是本地方法,这里的值是Undefined。
1.7 栈 & 堆 溢出
栈溢出:Stackoverflow
堆溢出:Out Of Memory
2. JVM从堆角度划分
2.1 堆 & 非堆 & 离堆堆
- 堆
堆用来存放所有的对象和数组,在堆内空间又分为年轻代和年老代。
- 年轻代
年轻代分为伊甸区和幸存区。所有对象诞生于伊甸区,然后回收后经过幸存区。
- 伊甸区
所有对象诞生于伊甸区。
- 幸存区
之所以使用两个幸存区,是为了在每次回收对象后,可以进行内存碎片整理。以利用更有效使用内存。
一区和二区也称为from区和to区,每次有一个区是空间是空的。但对象回收期间每个幸存区只经过一次。
- 幸存一区
- 幸存二区
- 年老代
- 非堆
非堆是JVM内在堆外部分的内存,主要包含代码缓存区、压缩类空间和元数据区。JDK1.8之前称为永久区。
- 离堆
离堆是操作系统内JVM之外的内存空间。java可以直接操纵jvm之外的内存空间。
2.2 参数调整
jdk1.8之后,没有永久代的概念了,改成了元空间的叫法。而且官方文档上说不会再出现永久区的溢出问题,比如在使用maven进行编译时常常导致的问题。
参数 | 解释 | 示例 | 备注 |
-Xss | 栈大小 | -Xss100m | |
-Xms | 初始堆大小 | -Xms100m | |
-Xmx | 最大堆设置 | -Xmx100m | |
-Xmn | 年轻代设置 | -Xmn100m | |
-XX:NewSize | 年轻代大小 | -XX:NewSize=100m | |
-XX:MaxNewSize | 年轻代最大值 | -XX:MaxNewSize=100m | |
-XX:NewRatio | 年老代是年轻代的倍数 | -XX:NewRatio=3,默认2 | |
-XX:SurvivorRatio | 伊甸区是单个幸存区的倍数 | -XX:SurvivorRatio=1,默认6 | |
-XX:MetaspaceSize | 元空间大小 | -XX:MetaspaceSize=1g | not work |
-XX:MaxMetaspaceSize | 最大元空间 | -XX:MaxMetaspaceSize=2g | not work |
-XX:CompressedClassSpaceSize | 压缩类空间 | -XX:CompressedClassSpaceSize=2g | not work |
-Xverbosegclog | 记录gc详细日志到文件 | -Xverbosegclog:/home/1.log | WAS(Websphere application server)中使用 |
-Xloggc | 记录gc日志 | -Xloggc:/home/1.log | JDK非标选项 |
3. JVM相关工具
3.1 jvisualvm
打开:Windows+R --> jvisualvm
打开IDEA中运行程序,就能看到 jvisualvm 界面中的情况
将所有区设为100M:
-Xms400m -Xmx400m -Xmn300m -XX:SurvivorRatio=1
3.2 jconsole
打开IDEA中运行程序
打开:Windows+R --> jconsole
3.3 jmap
3.4 jstat
- jstat查看帮助
- 查看jstat选项
- 查看jstat的gc情况
1秒钟1采样,采样100个样本,数字是进程id
- 各字段含义
列名 | 说明 |
---|---|
S0C | 幸存一区容量(Survivor,Capacity,KB) |
S1C | 幸存二区容量 |
S0U | 幸存一区使用的大小(Utility,KB) |
S1U | 幸存二区使用的量 |
EC | 伊甸区容量 |
EU | 伊甸区使用量 |
OC | 年老代容量 |
OU | 年老代使用量 |
MC | 方法区容量 |
MU | 方法区使用量 |
CCSC | 压缩类空间容量 |
CCSU | 压缩类空间使用量 |
YGC | 年轻代gc次数 |
YGCT | 年轻代gc时间 |
FGC | Full GC次数 |
FGCT | Full GC时间 |
GCT | GC总时间,FCCT + YGCT |
4. GC
4.1 什么是GC
GC 垃圾回收(garbage collection)
主要作用是回收程序中不再使用的内存。
为了减轻开发人员的工作,同时增加系统的安全性和稳定性,java语言提供了垃圾回收器来自动检测对象的作用域,可自动地把不再被使用的存储空间释放掉。主要的任务是:分配内存,回收不再被引用的对象的内存空间。
对象回收的前提是没有任何引用能够直接或间接到达他。
Java程序中显式将对象置为null是个不错的操作,起码保证了对象被回收的前提条件,但是显式调用System.gc()会显著降低系统性能。
年轻代上发生的gc称为minor gc。java程序中,大部分的对象是“夭折”的,意思就是对象在minor gc的时候就被回收掉了,没有多少对象会进入到年老代。
年老代上发生gc称为full gc或major gc,minor gc没有回收掉的对象会拷贝到年老代中。
元空间(jdk1.8之前称为永久代),也就是方法区存放的是类常量以及字符串常量。该区域也会发生gc,并且这部分的gc也算作major gc。
4.2 相关概念
并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行。而垃圾收集程序运行在另一个CPU上。
4.3 GC类型
- 1. Serial GC
串行gc,配置参数为: -XX:+UseSerialGC 。
采用“mark-sweep-compact”算法,mark是标记依然存活的对象,sweep清理掉回收的对象,compact是压紧内存空间,可以理解为内存碎片整理。
使用一个线程执行gc,串行gc很少使用。
- 2. Parallel GC
并行gc,配置参数为: -XX:+UseParallelGC。
串行gc使用一个线程执行gc,并行gc使用多个线程执行gc,因此在多核或是内存充足的情况下可以使用。串行gc很少使用。
- 3. Parallel Old GC
在JDK5之后才出现的算法,与并行gc算法的不是是针对年老代gc的算法采用的是“mark-summary-compact”。summary和sweep的不同是将gc之后幸存的对象放置到gc余弦处理好的不同区域,算法相对sweep来讲稍微复杂些。
配置参数为: -XX:+UseParallelOldGC
- 4. CMS GC
并行gc,该算法相较于之前的gc算法复杂得多。过程是“mark-sweep”阶段,没有了compact阶段。而且mark阶段又分成了initial mark和mark,其中initial mark需要stop-the-world,但是时间非常短,这一步主要是查找那些距离类加载器非常近的对象。之后的mark阶段是可以并行,即不需要stop-the-world,该步骤中,所有被幸存对象引用的对象会被确认是否已经被追踪和校验。remark阶段正如其名称一样,再一次检查那些在并行标记中增加或删除的对象,相当于验证过程。最后的并行sweep阶段开始执行gc过程,一旦采用该中gc,由gc导致的暂停时间非常短暂。因此CMS GC也叫低延迟gc,常用对响应时间非常苛刻的场景下。但CMS GC也有缺点:
占用更多的内存和cpu
默认不支持compact操作
如果因为碎片过多,导致不得不执行compact操作时,stop-the-world时间要比其他任何gc都要长,需要考虑compact任务的发生频率和执行时间。
配置参数为: -XX:+UseConcMarkSweepGC
- 5. G1 GC
G1类型是垃圾回收优先类型,在jdk1.7才正式发布的一个算法。G1的结构如图:
在该类型下,不再有年轻代和年老代的概念。如图所示,每个对象被分配到不同的格子,随后执行gc。一个区域装满后,对象被分配到另一个区域,并执行gc。中间不再有从年轻代到年老代转义的三个步骤了。该类型为替代CMS类型而创建,因为CMS在长时间持续运行时导致很多问题。
配置参数为: -XX:+UseG1C
G1的最大好处是性能,他比任何一种GC都快,但是一定要在成熟的jdk版本上使用它。
总结
收集器 | 串行、并行or并发 | 新生代/老年代 | 算法 | 目标 | 适用场景 |
---|---|---|---|---|---|
Serial | 串行 | 新生代 | 复制算法 | 响应速度优先 | 单CPU环境下的Client模式 |
Parallel | 并行 | 新生代 | 复制算法 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
Parallel Old | 并行 | 老年代 | 标记-整理 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
CMS | 并发 | 老年代 | 标记-清除 | 响应速度优先 | 集中在互联网站或B/S系统服务端上的Java应用 |
G1 | 并发 | both | 标记-整理+复制算法 | 响应速度优先 | 面向服务端应用,将来替换CMS |
4.4 Demo
Hello类
- class Hello
- {
- public static void main(String[] args) throws Exception
- {
- //指定循环次数
- int count = Integer.parseInt(args[0]) ;
- //指定byte数组大小
- int size = Integer.parseInt(args[1]) ;
- for (int i = 0 ; i<= count ; i++) {
- byte[] bytes = new byte[size] ;
- }
- }
- }
测试类中的 testProcess() 方法,测试5种垃圾回收类型所需要的时间
- @Test
- public void testProcess() throws Exception {
- //5中gc算法
- String[] gcs = {
- "UseSerialGC" ,
- "UseParallelGC" ,
- "UseParallelOldGC" ,
- "UseConcMarkSweepGC" ,
- "UseG1C"
- } ;
- Runtime r = Runtime.getRuntime();
- for(String gc :gcs){
- System.out.print(gc + "\t: ");
- for(int i = 0 ; i < 3 ; i ++){
- String javapc = String.format("java -Xms500m -Xmx500m -XX:NewSize=7m -XX:MaxNewSize=7m -XX:SurvivorRatio=5 -XX:+%s -cp d:/java Hello 10000 6000000" , gc) ;
- long start = System.nanoTime() ;
- Process p = r.exec(javapc);
- p.waitFor();
- System.out.print((System.nanoTime() - start) + "\t");
- }
- System.out.println();
- }
4.5 GC过程
GC 的回收过程是伊甸区已满,向幸存区的to区回收,同时幸存区的from区也会向to进行回收,注意幸存区有两个,同一时刻只有一个幸存区是空的,from区和to区会交替进行角色交换,但是对象在回收过程中只经过一次从from到to的过程,如果对象仍没有回收掉,就会进入到年老代。
4.6 GC优化
GC时,除了 GC 所需要的线程外,app的所有线程都会暂停,直到 GC 过程结束。因此有stop-the-world一次的说法。
对 GC 的优化,很多时候也是指要减少stop-the-world的时间。
JVM & GC 笔记的更多相关文章
- JVM GC笔记
堆分区:所有new的对象都会存放在堆中 > 新生代(Young Generation):存放生命周期短的对象,具体还分为Eden和Survivor两个区,其中Survivor分为Fro ...
- 【Java虚拟机】JVM学习笔记之GC
JVM学习笔记二之GC GC即垃圾回收,在C++中垃圾回收由程序员自己来做,例如可以用free和delete来回收对象.而在Java中,JVM替程序员来执行垃圾回收的工作,下面看看GC的详细原理和执行 ...
- JVM学习笔记(四)------内存调优【转】
转自:http://blog.csdn.net/cutesource/article/details/5907418 版权声明:本文为博主原创文章,未经博主允许不得转载. 首先需要注意的是在对JVM内 ...
- JVM学习笔记(四)------内存调优
首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提 ...
- java之jvm学习笔记十三(jvm基本结构)
java之jvm学习笔记十三(jvm基本结构) 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让概念在你的脑子里变成 ...
- jvm内存JVM学习笔记-引用(Reference)机制
在写这篇文章之前,xxx已经写过了几篇关于改jvm内存主题的文章,想要了解的朋友可以去翻一下之前的文章 如果你还不了解JVM的基本概念和内存划分,请阅读JVM学习笔记-基础知识和JVM学习笔记-内存处 ...
- JVM学习笔记-JVM模型
JVM学习笔记 == 标签(空格分隔): jvm 学习笔记全部来自于<深入理解java虚拟机>总结 jvm内存示意图 虚拟机栈(Java Virtual Machine Stacks): ...
- JVM 学习笔记记录
JVM 学习笔记记录 Sun JDK 监控和故障处理工具 名称 主要作用 jps JVM Process Status Tool, 显示指定系统内所有的HotSpot虚拟机进程 jstat JVM S ...
- JVM学习笔记-第三章-垃圾收集器与内存分配策略
JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...
随机推荐
- 从QQ音乐开发,探讨如何利用腾讯云SDK在直播中加入视频动画
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云发表于云+社区专栏 看着精彩的德甲赛事,突然裁判一声口哨,球赛断掉了,屏幕开始自动播放"吃麦趣鸡盒,看德甲比赛&q ...
- JDBC Oracle sys 用户连接
Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager.getConnection( &quo ...
- 数据存储之偏好设置NSUserDefaults
NSUserDefaults做数据存储也是比较常用,适合轻量级的本地数据存储,读取也很方便. 一.支持的数据类型如下图(NSString.NSArray.NSDictionary.NSData.NSI ...
- 并发编程之 CountDown 源码分析
前言 Doug Lea 大神在 JUC 包中为我们准备了大量的多线程工具,其中包括 CountDownLatch ,名为倒计时门栓,好像不太好理解.不过,今天的文章之后,我们就彻底理解了. 如何使用? ...
- Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)(转载)
Sql 四大排名函数(ROW_NUMBER.RANK.DENSE_RANK.NTILE)简介 排名函数是Sql Server2005新增的功能,下面简单介绍一下他们各自的用法和区别.我们新建一张O ...
- 常系数线性递推的第n项及前n项和 (Fibonacci数列,矩阵)
(一)Fibonacci数列f[n]=f[n-1]+f[n-2],f[1]=f[2]=1的第n项的快速求法(不考虑高精度). 解法: 考虑1×2的矩阵[f[n-2],f[n-1]].根据fibon ...
- 1.Strategy Pattern(策略模式)
策略模式(Strategy Pattern): 我的理解,将代码中每个变化之处抽出,提炼成一个一个的接口或者抽象类,让这些变化实现接口或继承抽象类成为具体的变化类.再利用多态的功能,可将变化之处用接口 ...
- macbook 外接显示器黑屏,不显示
我的mac本有点老了,11年底的那款 整了个显示器,刚开始连上没问题,后来开机状态拔了雷电线,再插 或者关机后莫名的原因再启动,显示器黑屏 网上好多方法都不行,自己总结了一个方法 拔掉连接线,关闭m ...
- socket 模拟 HTTP请求
一.socket介绍 网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用层.socket则是对TCP/I ...
- 使用ThinkPHP实现生成/校验验证码功能
首先了解父类Verity.class.php(ThinkPHP/Library/Think/Verity.class.php)中的一些函数 1:check() 校验验证码是否正确 2:entry()输 ...