java gc总结

gc主要工作于java堆(包含新生区Young Generation及年老区Old Generation),方法区(永久区Permanent Generation 1.7-)
堆主要放活动对象,其中:
新生区分为eden,to survivor, from survivor,大小默认为8:1:1
刚刚new的对象会放在新生区(其实是放eden),每次gc后还存活会将其存活计数器+1,当存活数达到15次左右,置入年老区。
方法区就比较复杂了,包括类加载器,常量池等等,主要是类的信息(即加载类时需要加载的信息,包括版本、域、方法、接口等信息),静态变量。
a.gc算法:
(1)复制算法(用于新生区):
eden,to survivor, from survivor这里简称a,b,c;回收过程如下
(a)对象不断地产生...放入a,活动区为a
(b)a满,根据root算法找出有用对象放入b(存货计数+1);清空a;活动区为a,b
(c)循环上一步,直到a,b都满
(d)对a,b都执行查找,将有用对象放入c;清空a,b;活动区为a,c
(e)这时每次a满,改为放c,a,c满,gc,然后改为使用a,b,如此类推。
复制算法适用于小量对象,因为复制会耗费相当的空间,复制后一并清除的做法好处是快速而不会产生碎片空间,通过不断切活动区保证内存区可用。
需要注意的是如果大对象放不下b或者c,直接放年老区;上面提到的存货计数达到一定程度也会移到年老区。
(2)标记-清扫算法(用于年老区,现在一般不用了):
找出所有不可达对象,并标记;标记完成后,一次性清除;会产生碎片空间,需要增加整理这一步。
(3)标记-整理算法(用于年老区,G1收集器以此为据):
可以说是上一算法的改进,先标记需要回收的对象,但是不会直接清理那些可回收的对象,
而是将存活对象向内存区域的一端移动,然后清理掉端以外的内存。
(4)gc一般不光顾永久区,故没有特别的算法,永久区的回收一般是:
(a)常量池中的常量,常量如果没有被引用则可以被回收
(b)无用的类信息(同时满足以下条件):
<1>类的所有实例都已经被回收了
<2>加载类的ClassLoader已经被回收
<3>类对象的class对象没有被引用(即没有通过反射引用该类的地方)
b.gc的步骤概念
Minor GC : 会清理年轻代的内存,主要是eden满触发
Major GC : 清理老年代,一般由Minor GC触发
Full GC  : 清理堆空间,如果Major GC没法解决,直接清理所有空间,如果还是无法分配空间,则报内存溢出
很多时候Full GC其实是执行了Minor GC+Major GC。
c.新版本jdk对方法区的更改
(1)1.8+取消了永久区Permanent Generation,改为元空间 Metaspace,两者都是对方法区的一种实现
元空间在本地内存,不在jvm内存中,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:
-XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:
如果释放了大量的空间,就适当降低该值;
如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。
除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:
-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集
用法:java -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m class
(2)String常量池从永久代移到了堆中

posted @ 2019-07-12 00:40  枫林晚月  阅读(658)  评论(0编辑  收藏  举报