071:jvm相关面试题
1 jvm组成部分相关面试题
JVM常用的调优参数
-Xmx 堆内存最大值 -Xmx2g 默认是系统内存的1/4
-Xms 堆内存最小值 -Xms2g
一般情况下最小堆内存和最大堆内存大小设置一样,每一次扩容都会进行一次full gc,减少full gc次数。
-Xmn 设置新生代的大小 默认是堆的1/3
-Xss 设置线程栈空间大小 -Xss256k
jvm运行时数据区域有哪几部分组成,各自作用;
- 线程共享
堆:new出来的对象放在堆中,(对象可能会有栈上分配(内存逃逸分析))
方法区(元空间):静态变量,常量,class对象 - 线程独占
栈:栈的内部由栈帧组成 先进后出;栈帧(局部变量表、操作数栈、动态链接、返回地址)
PC寄存器(程序计数器):指向当前线程执行到哪里
本地方法栈:native修饰的方法
2 jvm垃圾回收相关面试题
gc算法有哪些?
分代算法:根据对象的存活周期的不同将内存划分成几块,新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
复制算法:将可用内存分为两块,from域和to域,每次只是使用from域,to域则空闲着。当from域内存不够了,开始执行GC操作,这个时候会把from域存活的对象拷贝到to域,然后直接把from域进行内存清理。
标记清除:1.标记阶段:找到所有可访问的对象,做个标记;2.清除阶段:遍历堆,把未被标记的对象回收。
标记压缩:标记清除算法和标记压缩算法非常相同,未被标记的对象压缩再回收,解决内存碎片化。
引用计数:如果一个对象没有被任何引用指向,则可视之为垃圾。
可达性分析法(根搜索算法):通过一系列名为”GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
哪些可以作为 GC Roots 的对象:
局部变量、静态变量、本地方法栈、静态常量(static final)
你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms
Serial:单线程收集 非单核服务STW比较长
ParNew:多核情况下执行速度比较快(和cms一起使用)
Ps:重点在吞吐量:(用户线程执行时间)/(用户线程执行时间+gc执行时间)
CMS大体分为4部分
初始标记:标记老年代直接与gc root相关连的对象 (STW)
并发标记:上面标记的gcroot对象下关联的对象(非直接),用户线程会和gc一起执行
重新标记:标记那些新生代可达却引用到老年代的对象,还有一些刚进来老年代的对象(STW)
并发清除:清除老年代没有做标记的对象(和用户线程一起执行)
什么是Full GC?minor GC? major GC? STW?
minor GC:新生代回收的gc(STW)
major GC:老年代回收的GC
Full GC:minor GC+major GC
STW:stop the world,gc执行的时候停止所有的用户线程
jvm中一次完整的GC流程(从ygc到fgc)是怎样的,重点讲讲对象如何晋升到老年代
正常流程:
经过15次的ygc(复制算法)移入老年代
大对象直接回进入老年代
非正常:
动态年龄:S区50%以上的对象年龄>S区的平均值就会进入老年代(老年代不足发生full gc)
空间分配担保:s0或者s1放不下这些对象,进行一次空间分配担保(老年代剩余空间大于历代s区进阶的平均值)担保成功,失败发生full gc
方法区不足也会发生full gc/手动执行System.gc()也会触发full gc
3 oom异常定位相关面试题
如何判断是否有内存泄露
内存泄漏特点:因为对象不能被gc回收就会导致内存泄漏,jstack 看看经过gc之后的老年代对象是否被回收。
eg:第一次gc后老年代大小200m,第二次gc 300M,第三次gc350M,基本可以确定产生内存泄漏问题。
服务不可用,jstack 看到fgc执行次数远远大于ygc,产生内存泄漏问题。
OOM说一下?怎么排查?哪些会导致OOM? OOM出现在什么时候
标准的内存溢出:如后台没写分页(前端做的分页),数据量很大报内存溢出错误,报错后对象就会被回收;
内存泄漏产生的内存溢出:泄漏的对象不会被回收掉,直到对象把堆内存占满导致整个服务不可用。
定位:打印dump文件去用jvisualvm工具去查找大对象。
4 引用相关面试题
Java 中都有哪些引用类型?
强引用:Object o = new Object(); gc不会去回收强引用的对象;
软引用:SoftReference 当堆内存占满时就会回收这里面的对象(用来做缓存);
弱引用:WeakReference 只能存在于下一次gc之前:反生gc就会被回收;
虚引用:Object o = new Object(); o=null;提醒gc来回收这个对象