jvm知识总结

jvm知识总结
学习jvm主要是为了在敲写代码的时候更好的提高系统的性能,因为jvm是系统实例和一些静态变量存放保存的关键,了解jvm就可以更好的把系统空间利用好。
3.1 jvm内存模型:网上有很多很好的图片归总,我这里就按内存类别归类了一下(主要是因为这个是出现问题的关键)
线程安全分类
内存私有区:程序计数器、栈
内存共享区:堆、方法区
oom
会出现的位置:堆、栈、方法区
3.2 介绍
程序计数器:用于记录线程执行字节码行号的指示器,每条线程都会创建一个自己程序计数器,这是为一块不会出现oom的位置
栈:每个方法的调用都会创建一个栈帧,栈帧又包含局部变量表(非基本类型是地址,基本类型会在局部变量表创建)、动态连接、返回出口、操作数栈,每个方法的执行就是一个栈帧的入栈到出栈的过程,这个位置和线程息息相关,所以出现oom的时候也可以考虑这个位置,因为一个栈的创建是需要消耗内存资源如果线程创建的过多会出现oom,同时栈帧的大量创建也会出现oom;
方法区:被jvm加载的类信息,静态变量,常量,及时编译器编译编译后的代码等数据;
堆:(jdk1.8,jdk最新的版本内存使用G1垃圾处理不区分年代)分为年轻代和老年代,年轻代又分为伊甸园和幸存区(幸存1和幸存2,分为两个主要是为了垃圾算法的复制算法),主要存放创建的对象和数组,是垃圾回收处理的重要位置
3.3 一些jvm设计理念
3.3.1 为什么会划分年轻代和老年代
设置分代处理主要目的是提高内存的使用率,提高使用率的根本就是管理对象的销毁和创建;堆的内存分为年轻代和老年代,默认内存比为1:2,,可以通过xx newratio 之所以需要老年代空间大是因为如果老年带满了会出发fullgc,频繁的fullgc会影响系统的性能,所以在条件允许的情况下尽量使老年代空间大,年轻代中分为Eden+s0+s1,默认比为8:1:1,通过xx :SurvivorRatio设置幸存区,年轻代设置这样的格式主要是为了处理大量新创建的对象大部分都会死亡,只有少部分幸存,所以Eden区的内存大一些,分为两个幸存是年轻代使用的是复制算法的垃圾回收机制,复制算法没有零碎话的内存碎片同时因为是复制清除,所以效率比较高,应对于这种存活少的情况是很适合使用的,同时每次幸存的对象都是会有幸存标识,默认是16次会进入老年代空间(XX:+MaxTenuringThreshold设置幸存),这样会大大减少对象进入老年代,在年轻代只会出发minor gc(耗时短),减少了老年代的full gc(耗时长)
3.3.2 垃圾回收算法
Serial收集器: 单线程的收集器,收集垃圾时,必须stop the world,使用复制算法。
ParNew收集器: Serial收集器的多线程版本,也需要stop the world,复制算法。
Parallel Scavenge收集器: 新生代收集器,复制算法的收集器,并发的多线程收集器,目标是达到一个可控的吞吐量。如果虚拟机总共运行100分钟,其中垃圾花掉1分钟,吞吐量就是99%。
Serial Old收集器: 是Serial收集器的老年代版本,单线程收集器,使用标记整理算法。
Parallel Old收集器: 是Parallel Scavenge收集器的老年代版本,使用多线程,标记-整理算法。
CMS(Concurrent Mark Sweep) 收集器: 是一种以获得最短回收停顿时间为目标的收集器,标记清除算法,运作过程:初始标记,并发标记,重新标记,并发清除,收集结束会产生大量空间碎片。
G1收集器: 标记整理算法实现,运作流程主要包括以下:初始标记,并发标记,最终标记,筛选标记。不会产生空间碎片,可以精确地控制停顿。
2)CMS收集器和G1收集器的区别:
CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用;
G1收集器收集范围是老年代和新生代,不需要结合其他收集器使用;
CMS收集器以最小的停顿时间为目标的收集器;
G1收集器可预测垃圾回收的停顿时间
CMS收集器是使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片
G1收集器使用的是“标记-整理”算法,进行了空间整合,降低了内存空间碎片。
jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
3.3.3 gcroot有哪些
虚拟机栈中的对象,方法区中静态和常量对象,本地方法栈中jni引用的对象
3.3.4 oom的分析
思路:oom的位置,堆、栈、方法区,主要是从各个部分的存储信息来进行问题的具体分析,具体上面已经提到过,举个真是的线上问题,具体业务就不说了,后台的逻辑是使用了一个缓存线程池,正常的话是由一个请求的话会分发10个线程去处理相关业务,但是,前端的逻辑有问题导致1分钟内出现了1万次的请求,直接服务器宕掉了,后来通过后台的内存管理看到是栈的内存溢出了,所以上面的文章有提到过缓存线程池谨慎使用。
3.3.5 jvm的一次完整的gc(jdk1.8)
思路:内存+minor gc + minor gc + full gc
内存分为年轻代和老年代,年轻代又分为Eden区和S0,S1,当Eden满了的时候,会触发minor gc,幸存下的对象会进入S0,对象年龄加1,当Eden区再次满了的时候会再次触发minor gc,将幸存下的Eden和S0的对象复制到S1同时清除Eden和S0,年龄加1,如此往复,年龄到16(默认)的会被移动到老年代,正常情况下,到了老年代满了的时候会先触发年轻代的minor gc,如果minor gc还是无法满足,这个时候会触发full gc,另外有特殊情况就是幸存区满了,但是年龄没有到16,这个时候也会触发minorgc,如果年轻代还是无法满足的话,会将幸存区的对象直接放入老年代(这个时候需要调整一下虚拟机内存的分配)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值