什么是垃圾回收机制
C/C++语言 是手动来回收堆内存里不再使用的对象,而JAVA则是由JVM来自动回收
如何确定内存需要被回收了
标记 ,标记正在使用的内存,不在使用的内存,其中有2种内存
- 对象内存回收,即堆内存的回收,使用可达性分析算法来回收
- 方法区回收 这一节没有细说
可达性算法
可达性算法有一个根GCRoots,然后将所有相关的对象与它相连,如果某个对象在某个时候不可达到GCroots,那么它就可以被回收
具体的算法实现
所有的都是基于标记--清除这一算法的,然后有2种改进型
- 标记-清除 优点:快 缺点:有内存碎片问题(就是内存虽然还有很多空间,但却不连续,实际上是不能存储数据的)
- 标记-复制-清除: 优点:解决了碎片问题 缺点:占用空间
- 标记-清除-整理 在1的基础上,将内存整理成连续的 缺点:慢
具体的JVM实现
可以看到以上三种方法各有利弊,所以JVM实现的时候,在不同的场景使用不同的方法
分代收集
JVM大多数会使用分带收集实现,即新生代-次新生代-次次新生代--老生代
大概的算法就是
- 新建的对象放在新生代,使用标记-清除 这种方法,速度快
- 经历一次GC的,给它累加一个计数器,然后放到次新生代
- 当一个对象经历了数次GC,计数器累加到一定的次数时,JVM认为他经常使用,所以放到老生代,老生代使用标记-清除-整理的方法
- 空间大的对象也会直接放到老生代
经历多少次放到老生代,多大的对象会放到老生代,这些都是可以用参数来设置的
收集器
并行收集器
跟串行收集器的区别就是新生代GC和老生代GC一起进行,可以设置GC时间和吞吐量等值,可以自动进行适应性调整Eden,Surviror大小和MaxTenuringThreshold大小,感觉可以简单理解成多线程了
吞吐量 用户代码运行时间/(用户代码运行时间+GC时间)
可以设置的参数
- -XX:ParallelGCThreads 设置用于垃圾回收的线程数。通常情况下可以和CPU数量相等
- -XX:MaxGCPauseMills 设置最大垃圾收集停顿时间。它是一个大于0 的证书
- -XX:GCTimeRatio 设置吞吐量大小,它是一个0-100之间的整数
- -XX:UseAdaptiveSizePolicy: 打开自使用GC策略,达到在对大小、吞吐量和停顿时间之间的平衡
ParallelScavenge和Parallel Old
服务器模式默认使用这个并发收集器,它有年轻代和老年代两个实现
并行收集器G1
JDK1.9后默认的收集器,不区分年轻代和老年代的实现