java垃圾回收机制是按年代分的,青年代、老年代、永久代
青年代
java所有的垃圾回收对象都会优先放在青年代内,当青年代满了之后,还要创建新的对象,就会触发垃圾回收,将所有未被引用的对象回收
回收算法--复制算法
分配给青年代的内存会被划分为三块Eden跟两块Survivor(幸存者) 如果有100M内存就会被分为两个Survivor各10M ,Eden80M
对象开始都在eden内存内,但是当eden区满了的时候就会触发gc,清除所有未被引用数据,并将有引用的数据移到Survivor区,当eden再次满了触发gc时,会将Survivor的存活数据跟新的存活数据移动到另一个Survivor内,这样就能保持内存使用有90%的使用率,而不是之前的50%
如果对象很大超出Survivor大小怎么办
1.每次gc之前都会判断存活数据大小是否小于老年代内存
2.动态年龄判断
假设有两个对象,年龄都是两岁,但是加起来已经超出Survivor区内存的一半大小了,那就会进入老年代
3.大对象直接进入老年代,可以设置 -XX:PretenureSizeThreshold 参数(字节)大于设置
大小直接进入老年区
GC后的对象太多太大无法放入Survivor区
1.先判断老年区空间是否大于青年代全部存活对象。如果是则进行gc,存活对象进入老年区
2.如果老年区空间小于青年代存活对象大小,如果 -XX:-HandlePromotionFailure 参数打开
则判断老年代可用空间是否大于之前进入老年代对象的平均大小,如果是则让数据进入老年代
3.如果老年代可用空间小于进入对象平均大小,触发老年代gc,空间足够则进入
老年代
对象会有限创建在青年代内,但是如果他一直有被引用,比如常量实列,那么每经过一次垃圾回收就默认他涨一岁,当他达到15岁时,就会被移入老年代,那么老年代内都时长时间被引用的对象,如何垃圾回收呢?同理,老年代满的时候,就会触发垃圾回收机制
永久代
其实指的就是方法区,永久代会不会有垃圾回收呢?会,当类没有实列也没有引用m加载类的calssloader也被回收时,这个类就会被回收