1. System.gc()
System.gc()我们都知道是手动垃圾回收,这点无需多说,今天我们来了解一下System.gc()是怎么进行垃圾回收的。
System.gc()内部调用了 Runtime.getRuntiom
public static void gc() {
Runtime.getRuntime().gc();
}
在往深一层则是本地方法了
public native void gc();
System.gc()会执行FullGC,对新生代和老年代进行回收
注意: 此时垃圾回收线程可能并不会立即执行
证明:
package com.zy.study14;
/**
* @Author: Zy
* @Date: 2021/12/29 11:13
* 测试system.gc()方法
*/
public class SystemGcTest {
public static void main(String[] args) {
new SystemGcTest();
// 告知垃圾回收器执行垃圾回收,当并不一定立刻执行
// 证明如下: 如果执行了就会执行finalize方法,否则程序结束,垃圾回收线程也不会执行
System.gc();
// 立刻执行对象的finalize方法
//System.runFinalization();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("执行了finalize方法");
}
}
以下五种情况测试System.gc对对象的回收,同时验证垃圾回收算法的回收。
System.gc对对象的回收情况:
package com.zy.study14;
/**
* @Author: Zy
* @Date: 2021/12/29 11:30
* 测试垃圾回收对象
* -XX:+PrintGCDetails 打印gc细节
*/
public class SystemGcObjectTest {
public void test1(){
// 栈中有引用不会回收
byte[] buffer = new byte[10*1024*1024];
System.gc();
}
public void test2(){
// 将引用置空,此时可以回收
byte[] buffer = new byte[10*1024*1024];
buffer = null;
System.gc();
}
public void test3(){
// 代码块中引用并没有被覆盖,局部变量表中深度为2,第一个变量为this,第二个仍然为buffer,有该引用,所以不会被回收
{
byte[] buffer = new byte[10*1024*1024];
}
System.gc();
}
public void test4(){
// 代码块中buffer引用被被覆盖,局部变量表中深度为2,第一个变量为this,第二个buffer被覆盖为value,引用置空,所以被回收
{
byte[] buffer = new byte[10*1024*1024];
}
int value = 10;
System.gc();
}
public void test5(){
// 引用置空 会被回收
test1();
System.gc();
}
public static void main(String[] args) {
SystemGcObjectTest systemGcObjectTest = new SystemGcObjectTest();
systemGcObjectTest.test1();
}
}
通过对打印的gc信息可以观察到是否符合该方法中描述的回收情况,同时可以结合jclasslib查看局部变量表引用信息.
方法1,2,5都是比较简单的
比较复杂的就是3和4
针对3来说:
局部变量表的深度为2,但是变量表里只显示this对象,索引为1的仍然是代码块中的buffer引用.所以不会回收.