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