今天在技术群里被大佬问了一堆jvm的问题。。收集记录下来。。并且附上我的答案(没有百度的,不可尽信,仅仅是我看《深入理解java虚拟机》的粗浅回答)
1、堆被分成了新生代和老年代,什么对象会进入老年代。
答:
(1)大对象(对象大小超过设定的阈值),直接到老年代。
(2)在年轻代survivor区域存活minor gc次数超过指定次数的对象。默认是15次。可通过参数设置。
(3)survivor中存活的对象,存活次数相同的对象内存总和大小超过survivor的一半,那么大于等于这个存活次数的对象都会进入到老年代。
2、如何判断对象是否可回收?
(1)根据GC roots 进行可达性分析。
3、哪些对象可以做GC roots?
(1)、虚拟机栈中的每个栈帧中的局部变量表中的对象(即正在被调用的方法中的局部变量)
(2)、方法区中静态变量
(3)、方法区运行时常量池里的引用类型常量。(运行时常量池除了String和其他基本类型的包装类,还有啥引用类型?而String和包装类是不可变的啊)
(4)、本地方法栈中使用的对象。(这个不懂)
4、如何解决内存泄漏?
这个就要好好利用jdk本身提供的jmap工具了。
(1)用jmap把堆的当前快照文件拿到。
(2)使用专门的工具解析这个快照文件,貌似jdk里也有一个工具可以简单解析,转为图形界面。
(3)使用jmap本身参数可以查看占用内存对象。
(4)定位到具体代码,然后修改代码。
5、死锁如何解决?
使用jstack工具可以查询当前堆栈信息,并且会判断死锁标识。。
阿里开源的arthas也可以查看。。
6、触发gc的条件有哪些?
(1)年轻代内存不够了,触发minor GC
(2)老年代内存不够了,触发full GC/major GC
(3)方法区(永久代)内存不够了,触发Full GC
(4)minor GC时,如果有存活对象要晋升到老年代,如果老年代剩余空间大小小于历次平均晋升的对象大小,那么老年代会进行GC,此时是Full GC。
(5)代码中使用System.gc,会建议垃圾收集进行GC,但GC不一定听取建议。。不过在满足某些条件时还是会听取建议的(项目中一般不显示这么调用,本来就不一定立即生效)
(6)所谓大对象,是指需要大量连续内存空间的java对象,例如很长的数组,此种对象会直接进入老年代,而老年代虽然有很大的剩余空间,但是无法找到足够大的连续空间来分配给当前对象,此种情况就会触发JVM进行Full GC。