4大垃圾回收思想:
引用计数(可能会死循环持有) , 复制( 新生代 ,因为对象生命周期短) , 标记清除 和 标记整理 (老年代)
什么时候会进行新生代的垃圾回收?
新生代里eden区和survivor1区空间快满了,就会触发MinorGC,把存活的对象移动到survivor2区中。
接着,就使用eden和survivor2区来分配新的对象。
新生代满了哪些引用的对象是不能回收的?
JVM中使用了一种GCRoot的可达性分析算法,通过对每个对象,都分析一下有谁在引用他,然后一层一层往上去判断,看是否有一个GC Roots。
Java中对象的引用类型有那些?
强引用:就算OOM也不会对对象进行回收,会造成内存泄漏
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = obj1;
obj1 = null;
System.gc();
System.out.println(obj1); // null obj1已经被回收
System.out.println(obj2); //java.lang.Object@74a14482 obj2没有被回收
}
软引用:内存足够不进行回收,内存不够的话才进行回收 VM options: -Xms20M -Xmx20M
常用于:用HashMap来保存图片的路径 和 相应图片关联的软引用之间的映射关系,避免OOM的问题
public static void main(String[] args) {
Object obj1 = new Object();
SoftReference<Object> softReference = new SoftReference<>(obj1);
System.out.println(softReference.get());
obj1 = null;
try {
Byte[] bytes = new Byte[30 * 1024 * 1024];
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println(softReference.get());
}
}
// java.lang.Object@74a14482
// null
// Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
// at suanfa.HashMapTest.main(HashMapTest.java:24)
弱引用:只要垃圾回收机制一运行,就会进行回收
虚引用:不常用,一般用于监控对象的回收信息
新生代回收后,什么对象会进入老年代?
1.躲过默认的15次垃圾回收的对象
2.动态年龄判断:当前存放的survivor区域,相同年龄的一批对象大于这块survivor区域的内存大小的50%,那么这批对象就可以直接进入老年代
3.大对象直接进入老年代,可以通过 " -XX:PretenureSizeThreshold" 设置为字节数, 1048576 字节 就是1M
(为了避免大对象,多次GC回收不掉,在 s0 s1复制来复制去,影响性能)
MinorGC后的对象太多无法放入Survivor怎么办?
1.在执行minorGC之前 ,JVM会先检查现有存活对象小于老年代剩余内存,判断老年代剩余的空间,能够存得下存活的全部对象
2.情况1不成立,会判断 之前 平均存活的对象大小 < 老年代剩余大小,确保担保成功,避免OOM。
什么情况会导致OOM?
1.深度的方法调用 StackOverFlowError
2.堆内存溢出, OutOfMemoryError: Java heap space
3.清理垃圾,但是很快有填满 GC overhead
4.nio程序在分配本地内存的时候,本地内存用光了,用光了,再次分配的时候,程序就崩了
5.MetaspaceOOM (重复吃Aug年间静态类变量)
6.一个应用进程创建了多个线程超出了系统的限制,linux默认1024,可以通过 /etc/security/limits.d/90-nproc.conf
系统 CPU 100%异常如何定位?
1.top占用最高进程
2.ps -ef | grep java |grep -v grep
3.ps -mp 5101 -o THREAD,tid,time
4.5102转成16机制的小写 13ee
5.jstack 5101 | grep 13ee -A60 打印出前60行