**
学习笔记,逐步添加
**
类初始化的时机?
1、当创建某个类的实例时(new、反射、克隆、反序列化等);
2、当调用某个类的静态方法时;
3、当使用某个类或接口的静态字段时;
4、当调用Java API中的某些反射方式时;
5、当初始化某个子类时;
6、当虚拟机启动某个被标名为启动类的类时。
什么时候会发生Minor GC(Young GC)?
1、当新生代中的对象越来越多,Eden区放不下了,就会触发Minor GC;
JVM中有哪些垃圾回收算法?
复制算法:针对新生代的垃圾回收算法;
标记整理算法:针对老年代的垃圾回收算法。
被哪些变量引用的对象是不能回收的?
JVM使用可达性分析算法来判定哪些对象可以被回收,就是对每个对象都分析一下谁在引用它,然后一层层向上判断,看是否有一个GC Roots,如下:
局部变量可以作为GC Roots;
静态变量可以作为GC Roots。
新生代中的存活对象何时进入老年代?
1、躲过15次Minor GC后,默认设置下,当对象年龄达到15岁时,就会转移到老年代,可通过“-XX:MaxTenuringThreshold” 来设置,默认15;
2、动态年龄判断,即当前存放对象的Survivor区里,一批对象的总大小大于了这块Survivor区域的内存大小的50%,那么此时大于等于这批对象年龄的对象,就可以直接进入老年代了;
3、大对象直接进入老年代,有一个JVM参数,“-XX:PretenureSizeThreshold”,设置为“1048576”字节,就是1MB,意思是创建大于这个大小的对象直接放入老年代;
4、当Minor GC后发现剩余的存活对象太多,无法放入另一块Survivor区时,这些对象就直接转移到老年代。
Java堆内存中分配的那些对象,到底会占用多少内存,一般怎么来计算和估算我们的系统创建的对象对内存占用情况?
一个对象对内存空间的占用,大致分为两块:
1、一个是对象自己本身的一些信息;
2、一个是对象的实例变量作为数据占用的空间;
比如对象头,如果在64位linux操作系统上会占用16字节,如果你的实例对象内部有int类型的实例变量,会占用4字节,如果是long类型的实例变量,会占用8字节。(暂不考虑JVM的补齐机制、指针压缩机制)
加载到方法区的类会被来及回收吗?什么时候被回收?为什么?
会回收
首先该类的所有实例对象都已经从java堆内存里被回收;
其次加载该类的ClassLoader已经被回收;
最后该类的Class对象没有任何引用。
满足以上条件就可以回收该类了。
老年代的Full GC比新生代Minor GC慢很多倍的原因?
Minor GC 直接从GC Roots出发追踪哪些对象是活的就行,新生代存活对象很少,这个速度极快,不需要追踪多少对象,然后直接把存活对象放入Survivor区中,一次性回收Eden和之前使用的Survivar区中的垃圾
Full GC在并发标记阶段,它需要去追踪所有存活对象,老年代存活对象多,这个过程会很慢;
在并发清理阶段,它不是一次性回收一大片内存,而是找到零散在各个地方的垃圾对象,速度也很慢;
最后还要执行一次内存碎片整理,把大量存活对象挪到一起,空出连续内存空间,这个过程还要“Stop the world”,就更慢了;
万一并发清理期间,剩余内存空间不足以存放进入老年代的对象,引发“Concurrent Mode Failure”问题,还要使用“Serial Old” 垃圾回收期,“Stop the world”之后慢慢重新来一边回收过程,这个更耗时。