1、如何判定对象为垃圾对象
-verbose:gc
-xx:+PrintGCDetail
1.1 引用计数法(很少使用)
在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,
当引用失效的时候,计数器的值就-1。
缺点:比如堆中对象相互引用,而在外部并没有对这些对象进行引用,其实他们还是垃圾,但是是因为引用值不为 0, 所以这些对象可能就不会被回收掉。
1.2 可达性分析法
定义一个GCRoot,通过模拟的引用链式进行查找(比如遍历某棵树,深度遍历、广度遍历),能找到的都是可用的, 如果引用断开,之前引用的全都失效,失效标识可以回收。
~可作为GCRoots的对象
~虚拟机栈
~方法区的类属性所引用的对象
~方法区中常量引用的对象
~本地方法栈中引用的对象
2、如何回收
2.1 回收策略
2.1.1 标记-清除算法(第一次标记,第二次遍历的时候清除)
存在的问题:1.效率问题 多次遍历空间
2.空间问题 清除之后留下一些琐碎的小空间,如果大的对象来之后无法即时放下,重新启动垃圾回收机制。
2.1.2 复制算法
线程共享区 :堆 (新时代堆(Eden 伊甸园 多、Survivor 存活区 少、Tenured Gen 无)、老年代堆)、方法区
线程独享区 :栈 、本地方法栈 、程序计数器
复制算法:把内存分为两块,在一块中进行标记操作,标记完的移到另一块区域,清空当前区域,再对另外一块区域进行操作,以此类推。
缺点:内存资源浪费,只用了一半
对该缺点进行改进:创建新对象主要是往Eden里放,如果满了就用surivor的其中一个。垃圾回收的时候会把存活的对象放到另一个Survivor中,反复此过程。这样就可以达到只浪费10%的存储资源。 当surivor中大于10%时,就把其中的扔到Tenured Gen的中(内存担保)。
2.1.3 标记-整理算法
进行移动,到达目的地之后进行统一清除2.1.4 分代收集算法
原理:Eden区域的进行复制算法,老年代的进行标记整理算法。