1.jvm内存分配与回收
1.1 对象优先在Eden区分配
新生代GC(Minor GC):指发生新生代的垃圾收集动作,Minor GC非常频繁,回收速度一般也比较快。
老年代GC (Major GC/Full GC):指发生在老年代的GC,出现了Major GC 经常会伴随至少一次的Minor GC(并非绝对),Major GC的速度一般会比Minor GC的慢10倍以上。
当对象在Eden 区没有足够空间分配,而且survior 区也无法存入时,只有通过分配担保机制把新生代的对象提前转移到老年代中去。老年代空间足够放这个对象时不会出现Full GC。
大对象直接进入老年代:大对象就是需要大量连续内存空间的对象(比如:字符串,数组)
为什么这么做:避免为大对象分配内存时由于分配担保机制带来的复制而降低效率。
长期存活的对象将进入老年代。默认年龄增加到15,就会晋升到老年代中,就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设置
2.如何判断对象可以被回收
2.1 引用计数法——没有使用,因为很难解决对象之间相互循环引用的问题。
2.2 可达性分析算法——通过一系列的被称为“GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。
2.3 finalize()方法最终判定对象是否存活
即使在可达性分析算法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历再次标记过程。
标记的前提是对象在进行可达性分析后发现没有与GC Roots相连接的引用链。
2.5 如何判断一个类是无用的类
1.该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例
2.加载该类的 ClassLoader 已经被回收
3.该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
垃圾搜集算法
标记-清除:
不足:
1.效率问题
2.空间问题(标记清除后会产生大量不连续的碎片)
复制算法:
为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收
标记-整理算法: