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 ...
随机推荐
- setup&hold
setup time:建立时间,也就是在时钟上升沿到来前,数据需要稳定的时间.hold time:保持时间,指的是在时钟上升沿到来后,数据还需要保持的时间.实际上设置setup time和hold t ...
- php功底你修炼到哪一级
第一阶段:基础阶段(基础PHP程序员) 重点:把LNMP搞熟练(核心是安装配置基本操作) 目标:能够完成基本的LNMP系统安装,简单配置维护:能够做基本的简单系统的PHP开发:能够在PHP中型系统中支 ...
- Spark2.1.0模型设计与基本架构(下)
阅读提示:读者如果对Spark的背景知识不是很了解的话,建议首先阅读<SPARK2.1.0模型设计与基本架构(上)>一文. Spark模型设计 1. Spark编程模型 正如Hadoop在 ...
- SQLServer之视图篇
1 视图介绍 视图是从一个或者几个基本表(或视图)导出的表.它与基本表不同,是一个虚表.数据库中只存放视图的定义,而不存在视图对应的数据,这些数据仍然存放在原来的基本表中.所以一旦基 ...
- [日常] Go语言圣经-Deferred函数
1.只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法.当defer语句被执行时,跟在defer后面的函数会被延迟执行.直到包含该defer语句的函数执行完毕时,defe ...
- Java基础——详尽说明try-catch-finally的用法
问:Java异常处理机制,理解了吗?Java异常处理,真的掌握了吗?什么是自定义异常?catch体里遇到return 是怎么处理?finally 体里有return怎么处理?catch 和 final ...
- 逆向工程生成的mybatis中mapper文件。mapper接口,实例化成对象
逆向工程生成的mybatis中mapper文件中,*mapper文件只是接口,而不是类文件.但是却可以通过spring的容器获得实例. 例如: //1.获得mapper代理对象,从spring容器获得 ...
- 方程整数解-2015省赛C语言A组第一题
方程整数解 方程: a^2 + b^2 + c^2 = 1000(或参见[图1.jpg])这个方程有整数解吗?有:a,b,c=6,8,30 就是一组解.你能算出另一组合适的解吗? 请填写该解中最小的数 ...
- Charlie's Change(完全背包+路径记忆)
Charlie's Change Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3176 Accepted: 913 D ...
- C#里面的事物回滚,解决同步数据插入时出现重复数据
什么是事物回滚: 举个栗子,你在你家的银行分行取钱,取完钱数据要同步,而且可能每个分行都有一个存储这些数据的数据库,分行的这些 存取的记录都需要实时同步,如果你取完500刚好断电了,好嘛,分行可能刚记 ...