文章目录
System.gc()的理解
在默认情况下,通过system.gc()者Runtime.getRuntime().gc() 的调用,会显式触发FullGC,同时对老年代和新生代进行回收,尝试释放被丢弃对象占用的内存。
然而system.gc() )调用附带一个免责声明,无法保证对垃圾收集器的调用。(不能确保立即生效)
JVM实现者可以通过system.gc() 调用来决定JVM的GC行为。而一般情况下,垃圾回收应该是自动进行的,无须手动触发,否则就太过于麻烦了。在一些特殊情况下,如我们正在编写一个性能基准,我们可以在运行之间调用System.gc()
代码演示是否出发GC操作
public class SystemGCTest {
public static void main(String[] args) {
new SystemGCTest();
// 提醒JVM进行垃圾回收
System.gc();
//System.runFinalization();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("SystemGCTest 执行了 finalize方法");
}
}
运行结果,但是不一定会触发销毁的方法,因为调用finalize()方法的Finalize线程级别比较低,调用System.runFinalization()会强制调用 失去引用对象的finalize()
SystemGCTest 执行了 finalize方法
手动GC来理解不可达对象的回收
代码如下所示:
public class LocalVarGC {
/**
* 触发Minor GC没有回收对象,然后在触发Full GC将该对象存入old区
*/
public void localvarGC1() {
byte[] buffer = new byte[10*1024*1024];
System.gc();
}
/**
* 触发YoungGC的时候,已经被回收了
*/
public void localvarGC2() {
byte[] buffer = new byte[10*1024*1024];
buffer = null;
System.gc();
}
/**
* 不会被回收,因为它还存放在局部变量表索引为1的槽中
*/
public void localvarGC3() {
{
byte[] buffer = new byte[10*1024*1024];
}
System.gc();
}
/**
* 会被回收,因为它还存放在局部变量表索引为1的槽中,但是后面定义的value把这个槽给替换了
*/
public void localvarGC4() {
{
byte[] buffer = new byte[10*1024*1024];
}
int value = 10;
System.gc();
}
/**
* localvarGC5中的数组已经被回收
*/
public void localvarGC5() {
localvarGC1();
System.gc();
}
public static void main(String[] args) {
LocalVarGC localVarGC = new LocalVarGC();
localVarGC.localvarGC3();
}
}
依次执行每个方法。
- 执行
localVarGC1()
时,输出的GC log如下:
[GC (System.gc()) [PSYoungGen: 12761K->10636K(76288K)] 12761K->10644K(251392K), 0.0077479 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[Full GC (System.gc()) [PSYoungGen: 10636K->0K(76288K)] [ParOldGen: 8K->10478K(175104K)] 10644K->10478K(251392K), [