JVM调优

原创
2018/09/27 19:59
阅读数 62

JVM参数配置

JVM提供了诸多的参数进行JVM各个方面内存大小的设置,为Java应用进行优化提供了诸多的工具,本文将会详细分析各个参数的功能与使用。

常见参数配置

-XX:+PrintGC      每次触发GC的时候打印相关日志

-XX:+UseSerialGC      串行回收

-XX:+PrintGCDetails  更详细的GC日志

-Xms               堆初始值

-Xmx               堆最大可用值

-Xmn               新生代堆最大可用值

-XX:SurvivorRatio  用来设置新生代中eden空间和from/to空间的比例.

-XX:NewRatio       配置新生代与老年代占比 1:2

含以-XX:SurvivorRatio=eden/from=den/to

总结:在实际工作中,我们可以直接将初始的堆大小与最大堆大小相等,

这样的好处是可以减少程序运行时垃圾回收次数,从而提高效率。

-XX:SurvivorRatio     用来设置新生代中eden空间和from/to空间的比例.

 

堆溢出:java.lang.OutOfMemoryError:java heap space 堆内存溢出 原因:内存不足 解决方法:JVM参数增大内存

垃圾回收基本原则:内存不足的时候去回收,内存如果足够,暂时不会回收。减少回收次数与回收时间(回收影响系统性能)

栈溢出:java.lang.StackOverflowError 递归调用会发生 解决方法:设置线程最大调用深度 -Xss5m

内存泄露、内存溢出区别:

内存溢出,是在 申请 内存空间时,超出最大堆内存空间。

内存泄露,使用因为内存空间没有及时的释放(不收垃圾回收器控制),长时间导致占用内存,最终导致内存溢出(太多static导致,IO流没有关闭)。

垃圾收集器:

并行回收与串行回收区别:多线程与单线程(服务器一般都是并行接收)

cms收集器:

jmeter压力测试工具:

jvm调优原则:1、减少垃圾回收次数 2、老年代空间大于新生代内存空间

调优:堆的初始值和堆的最大值最好一致(初始值太小会导致频繁的垃圾回收)

垃圾回收机制次数和最大堆内存没有关系,和初始堆内存有关系,最大内存做申请内存,核心还是初始内存

 

面试题:

1、JVM运行时数据区域有那几部分组成,各自的作用

线程共享:

    堆:new出来的对象

    方法区(元空间):静态变量、常量,class对象

线程独占:

    栈:局部变量,操作数栈

    PC寄存器(程序计数器):指向线程执行到什么地方了

    本地方法栈:native修饰的方法

从上面图中可以看出:Metaspace,Old,Eden,S0,S1,各自的空间占比,新生代采用复制算法进行垃圾回收

老年代采用标记/清除算法标记/整理算法

2、gc算法有那些,gc收集器有那些?

分代算法:

复制算法:默认采用

标记清除:

标记压缩:默认采用

引用计数:已被淘汰(存在循环引用的弊端),(存活)

给对象添加一个引用计数器,每当对象被引用一次就加1,引用失效时就减1。当为0的时候就判断对象不会再被引用

 

可达性分析:解决了循环引用的问题,(存活)

通过一个称为“GC Roots”的对象为起始点,搜索所经过的路径称为引用链,当一个对象到GC Roots没有任何引用跟它连接则证明对象是不可用的

新生代收集器:

    Serial:单核采用,非单核服务STW时间比较长

    ParNew:Serial的升级版,因为它支持多线程[GC线程],默认开启线程数和当前cpu数量相同,通过-XX:ParallelGCThreads来控制垃圾收集线程的数量。与cms配合使用

    Parallel Scavenge:采用复制算法的收集器,和ParNew一样支持多线程。Parallel Scavenge注重吞吐量,所以也成为"吞吐量优先"收集器,用户线程执行时间/(用户线程执行时间+gc时间)

老年代收集器:

    Serial Old:新生代的Serial一样为单线程,Serial的老年代版本,不过它采用"标记-整理算法"

    Parallel Old:支持多线程,Parallel Scavenge的老年版本,jdk6开始出现, 采用"标记-整理算法"【老年代的收集器大都采用此算法】

    CMS:CMS采用的是"标记-清除"(Mark Sweep)算法,而且是支持并发(Concurrent)的

启用CMS:-XX:+UseConcMarkSweepGC
1.初始标记:标记一下GC Roots能直接关联到的对象,速度很快【会STW,标记】
2.并发标记:GC Roots Tarcing过程,即可达性分析
3.重新标记:为了修正因并发标记期间用户程序运作而产生变动的那一部分对象的标记记录,会有些许停顿,时间上一般 初始标记 < 重新标记 < 并发标记
4.并发清除

    G1:它不属于新生代也不属于老年代收集器。用到的算法为标记-清理、复制算法。

开启选项 -XX:+UseG1GC 

3,Minor GC、Major GC、FULL GC、mixed gc

Minor GC:在年轻代Young space(包括Eden区和Survivor区)中的垃圾回收称之为 Minor GC,Minor GC只会清理年轻代.

Major GC:

Major GC清理老年代(old GC),但是通常也可以指和Full GC是等价,因为收集老年代的时候往往也会伴随着升级年轻代,收集整个Java堆。所以有人问的时候需问清楚它指的是full GC还是old GC。

Full GC:full gc是对新生代、老年代。也就是Minor GC+Major GC

mixed GC【g1特有】:混合GC,收集整个young gen以及部分old gen的GC。只有G1有这个模式

4、那些可以作为GC Roots的对象?

局部变量,静态常亮,本地方法栈,静态常亮 static final

5、jvm中一次完整的GC流程(从ygc到fgc)是怎样的,重点讲讲对象如何晋升到老年代

正常流程:经过15次ygc(复制算法)到老年代、大对象直接进入老年代

非正常流程:

    动态年龄:S去50%以上的对象年龄》S区的平均值就会进入老年代(老年代不足发生fullgc)

    空间分配担保(S区放不下这些对象,进行一次空间担保,失败就会发生fullgc)

方法区不足也会发生fullgc

6、如何判断是否内存泄漏

内存泄漏有什么特点:对象不能被gc回收就会内存泄漏

jstack查看进过gc执行后的老年代对象是否被回收。第一次 200M 2:300M 3:350M

服务不可用,jstack发到fgc的次数远远大于fgc的次数

7、OOM(内存溢出)说一下?怎么排查?那些会导致OOM?OOM出现在什么时候?

后台没分页,前端做分页,数据量很大的时候,堆装不下,就容易内存溢出。内存溢出报出错误,所有的对象都被回收。

内存泄漏产生的内存溢出:泄漏的对象不会被回收,直到我们的堆内存被占满,导致整个服务不可用

打印dump文件,用专门的工具去找大对象

8、java中有那些引用类型?

强引用:Object o = new Object(); gc不回去回收强引用的对象。

软引用:SoftReference;当我们堆内存占满的时候就会回收里面的对象。(一般用来做缓存,缓存框架都是用的这个对象)

弱引用:WearkReference 只能存在于下一次gc之前。发生minor major就会被回收

虚引用:Object o = new Object();

                o = null; 提醒我们的gc来回收这个对象。

 

参考链接:https://www.jianshu.com/p/76959115d486

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部