jvm GC收集器与内存分配(深入理解java虚拟机第三章)
本篇是《深入理解java虚拟机第三章》的笔记记录。
一 为什么要关注GC和内存分配?
需要排查各种内存溢出、内存泄漏问题时,或者当GC成为系统达到更高并发量的瓶颈时,需要对jvm的默认参数进行调节;
二 哪些内存需要回收?
方法区回收:废弃常量和无用类;
无用类:
该类的所有实例都被回收;
加载该类的ClassLoader已经被回收;
该类对应的java.lang.Class对象没有在任何地方被引用,无法再任何地方通过反射访问该类的方法;引用计数算法:给对象添加一个引用计数器,每当有一个地方引用它时+1,引用失效时-1,任何时刻计数器=0则对象不会再用到。但这个算法无法解决对象之间相互循环引用的问题;
可达性分析算法:GC Roots无法引用到的对象。即从GC Roots节点向下搜索,当一个对象到GC Roots没有任何引用链存在即此对象不可用; 引用 : 强引用、软引用、弱引用、虚引用;
GC Roots包括:
JVM栈中本地变量表引用的对象;
方法区中静态属性引用的对象;
方法区中常量引用的对象;
本地方法栈中JNI引用的对象;
三 什么时候回收?
程序计数器、jvm栈、本地方法栈 随着线程生死;
栈帧分配的内存随着栈帧的调用结束而被回收;
堆内存:
一般情况:
Minor GC: 当新生代中的Eden区没有足够空间时触发一次Minor GC;
Full GC(Major GC):当老年代没有足够空间时;
实际上:
四 如何回收
1 算法
(1)标记清除算法;
缺点: A 效率不足,标记和清除两个过程都效率不高;
B 清楚后会产生大量不连续的内存碎片,空间碎片太多导致当需要分配较大对象时,无法找到足够连续空间触发GC;
(2)复制算法;
缺点:将内存缩小为原来的一半;
优点:不会发生空间碎片;
应用:新生代使用的收集算法,将新生代划分为一块Eden,两块较小的Survivor空间,每次使用Eden与一块Survivor,回
收时将Eden和Survivor存货对象复制到另一块Survivor,清理原始Eden Survivor空间;
HotSpot虚拟机默认Eden和Survivor大小比例为8:1,可使用-XX:SurvivorRatio=8来调整;
当Survivor空间不够时,使用老年代进行分配担保;
(3)标记整理算法:将所有存活对象都向一端移动,然后清理掉端边界以外的内存;
优点:对象存活率较高时不进行复制操作,提高效率;
应用: 老年代;
(4)分代收集算法;
2 垃圾收集器
(1)Serial 收集器:
复制算法;
单线程执行;
执行过程中,用户的工作线程全部停掉;
应用:单CPU环境;
(2) ParNew 收集器:
复制算法;
多线程执行(并行,用户线程处于等待状态);
使用-XX:+UseParNewGC强制指定或者-XX:+UseConcMarkSweepGC的默认新生代收集器;
默认开启的收集线程数与CPU的数量相同,当CPU非常多,可使用-XX:ParallelGCThreads限制收集线程数;
应用:许多运行在server模式下的虚拟机新生代首选收集器,因为除了Serial收集器外,目前只有它能与CMS收集器
配合工作;
(3) Parallel Scavenge收集器:
新生代;
复制算法;
并行多线程收集器;
特点:目标是达到一个可控制的吞吐量 吞吐量=运行用户代码时间/(运行用户代码时间 + 垃圾收集时间),适用于
后台运算而不需要太多交互的任务
使用: -XX:MaxGCPauseMillis 控制最大垃圾收集停顿时间;(>0的毫秒数)
-XX:GCTimeRatio 设置吞吐量大小;(0-100)
-XX:+UseAdaptiveSizePolicy 开关参数,打开后不需要手动指定-Xmn,-XX:SurvivorRatio,
-XX:PretenureSizeThreshold等细节参数,自适应的调节策略;
(4) Serial Old 收集器
老年代;
单线程;
标记-整理算法
用途:CMS收集器后备;
(5) Parallel Old收集器
老年代;
多线程;
标记-整理算法;
对应Parallel Scavenge的收集器
用途:注重吞吐量以及cpu资源敏感的场所;
(6) CMS收集器(Concurrent Mark Sweep):
老年代;
并发收集器;
标记-清除算法;
目标:获取最短回收停顿时间,提升用户体验
用法:使用-XX:CMSInitiatingOccupancyFraction设定cms启动阈值(老年代使用空间的百分比)
-XX:+UseCMSCompactAtFullCollection(开关参数,默认开启) 设置CMS收集器在Full GC前开启内存碎片
合并整理过程;
缺点:
cpu资源敏感;
无法处理浮动垃圾,可能出现Concurrent Mode Failure失败而导致一次Full GC的出现;
产生大量碎片,可以使用-XX:+UseCMSCompactAtFullCollection开启内存碎片合并整理;
-XX:CMSFullGCsBeforeCompaction设置执行多少次不压缩的Full GC后来一次压缩的
默认值为0,即每次Full GC前都压缩;
(7)G1收集器
并行与并发;
将整个堆划分为多个大小相等的Region,根据各个Region的垃圾堆积价值大小优先回收价值最大的Region
独自可以管理整个GC,而且可以采用不同方式处理新创建的对象和已经存活了一段时间的对象获取更好的收集效果
不会有空间碎片;
可以预测的停顿(G1相对于CMS的优势,除低停顿外,还可以建立可以预测的停顿时间模型)
3 内存分配
(1) 对象优先在Eden分配
(2) 大对象直接进入老年代 -XX:PretenureSizeThreshold=3145728 大于3MB的对象直接进入老年代
(3) 长期存活的对象进入老年代 : Eden对象经过一次Minor GC后仍存活并且能够被Survivor所容纳将被移动到Survivor
空间中,对象年龄设置为1,对象在Survivor空间中没经过一次Minor GC年龄加1,当年龄增加到
-XX:MaxTenuringThreshold=1(默认15)时,对象会晋升到老年代
(4) 如果在Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象直接进入老年代;
jvm GC收集器与内存分配(深入理解java虚拟机第三章) 相关文章
PostgreSQL内存OOM控制策略导致数据库无法启动的诊断一例(如何有
简介: 你可能遇到过类似的数据库无法启动的问题,postgres@digoal- FATAL: XX000: could not map anonymous shared memory: Cannot allocate memoryHINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded availa
JVM飙高排查脚本-结构分析
简介: 该文章来自于阿里巴巴技术协会(ATA)精选文章。 大家都有过遇到线上程序LOAD突然狂飙的场景,要排查到为何狂飙,我们当务之急就是要找到导致CPU飙升的原因。如果是进程级的应用,如Nginx、Apache等都还比较容易排查,但如果是JVM中的某个线程导致的
硬盘和内存的区别是什么它们各有什么性能指标
区别:1、内存是计算机运行的场所,硬盘用来存放暂时不用的信息;2、内存中的信息会随掉电消失,硬盘中的信息可以长久保存。硬盘的性能指标,包括硬盘容量、硬盘速度、硬盘转速、接口、缓存、硬盘单碟容量等;内存的性能指标为容量、频率、延迟值。 内存:内
windows7的svchost.exe占用内存过高怎么办
windoes7的svchost.exe占用内存过高的解决办法:首先打开控制面板设置,找到管理工具项;然后找到服务项,双击并点击标准;最后设置关闭或者禁用即可。 windoes7的svchost.exe占用内存过高的解决办法: 1、当我们看到我们的任务管理器是这样的情况,电脑一般
内存映射
内存映射 Memory mapping 目标 关键字: 总览 用于内存映射的结构 struct page struct vm_area_struct struct mm_struct 设备驱动程序内存映射 Exercises 1.将连续的物理内存映射到用户空间 2.将不连续的物理内存映射到用户空间 3.映射内存中的读/写操作 4.显
java的class文件在jvm运行时数据区的过程
java的class文件在jvm运行时数据区的过程 今天在学习类加载的过程的步骤时感觉还是有点难度的,写个帖子记录一下 jvm运行时数据区图: 本地方法栈(线程私有) 登记native方法,在Execution Engine执行时加载本地方法库 程序计数器(线程私有) 就是一个指针,
由浅入深理解JVM虚拟机
由浅入深理解JVM虚拟机 由于笔者能力有限,会不断更新此文章,学到哪里更新到哪里. 目录 1 JDK8的JVM内存模型 2 JVM中有哪几块内存区域?Java 8之后对内存分代做了什么改进? 3 你知道JVM是如何运行起来的吗?我们的对象是如何分配的? 3.1 首先要知道JVM如何加
FD.io VPP:vlib buffer pool(vlib_buffer) 内存初始化
FD.io VPP:vlib buffer pool(vlib_buffer) 内存初始化 Table of Contents vlib buffer创建过程 vlib_buffer相关内存初始化 1、函数一开始就查询numa的个数 2、遍历numa节点来初始化 3、查询系统大页大
内存区划分
内存区划分 内存区划分 一.内存分配(汇编语言/高级语言) 二.划分 1.代码段 --text(code segment/text segment) 2.数据段 -- data 3.bss段--bss 4.stack: 5.heap: 三.instance analysis 一.内存分配(汇编语言/高级语言) 站在汇编语言的角度,一个程序分为:
JVM理解
JVM理解 套用文章 https://www.cnblogs.com/zyrblog/p/9941723.html https://www.cnblogs.com/zhangpan1244/p/6197832.html https://www.jianshu.com/p/3ffc6a8c012e https://blog.csdn.net/qq_41701956/article/details/80020103 JRE分为JVM与API,JRE为java
jvm GC收集器与内存分配(深入理解java虚拟机第三章) 图文文章
resetFields和clearValidate区别
resetFields和clearValidate区别 在使用element ui 进行表单校验的时候。混用了resetFields和clearValidate造成了个莫名奇妙的bug 记录下。 this. r e f s . f o r m . r e s e t F i e l d s ( ) ; / / 移 除 校 验 结 果 并 重 置 字 段 值 t h i s . refs
美团日志框架Logan(Android)学习
美团日志框架Logan(Android)学习 一、介绍 随着业务的不断扩张,移动端的日志也会不断增多。 当用户达到一定量级之后,某些用户的Bug却无法通过之前的跟踪定位方式来进行解决。 这时候我们需要一个移动端的日志收集工具。 Logan是美团移动端底层的基础日志库
超简单的openCV4环境配置教程
超简单的openCV4环境配置教程 目录结构 openCV4.4+VS2017+win10 配置包含目录 配置库目录 配置链接器 配置环境变量 运行测试代码 1.openCV4.4+VS2017+win10 1.1.openCV环境准备 去官网下载opencv4.4版本,选择windows的opencv版本 解压放在设定的目录下 1.2.V
素数筛——详解
素数筛——详解 判断一个数是否是素数,首先我们明晰素数的概念。 素数:素数一般指质数。质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。 暴力 由此我们可以从2遍历到x-1,判断x能否被整除,写出最简单暴力的IsPrime(int x) bool I