上篇说到Java垃圾回收(GC),由于某种原因,没有写完,本篇接着上篇继续。
上篇有一个例子(GCTest),程序运行的结果如果:
Program start...
Free/Total memory (bytes):1841832/2031616
After created three MyObject objects...
Free/Total memory (bytes):1836224/2031616
After released MyObject objects...
Free/Total memory (bytes):1835264/2031616
After run System.gc()...
Free/Total memory (bytes):1835432/2031616
可以发现程序一开始运行时,就已经使用了一些内存。接着当产生MyObject对象时,内存又减少了一些。可是很奇怪的是,当把三个MyObject对象引用设定为null后,系统没有把垃圾回收回来,反而更少了?这是因为调用System.out.println这个方法也是需要使用内存的,而且GC并没有被启动来回收这些没有用到的内存!
因为上例太短,不到三秒就执行完毕,系统当然来不及启动GC。虽然GC会视需要不定时地执行,但是我们也可以手动来调用它。调用GC的方式是使用System.gc(),它会帮忙调用Runtime.getRuntime().gc()。所以这两种方式都可以。
修改上例的程序,加上下面几行代码。
System. out .println( " After run System.gc()... " );
rt.freeMemory() + " / " + rt.totalMemory();
程序执行结果如下:
Program start...
Free/Total memory (bytes):1841344/2031616
After created three MyObject objects...
Free/Total memory (bytes):1836056/2031616
After released MyObject objects...
Free/Total memory (bytes):1835264/2031616
After run System.gc()...
Free/Total memory (bytes):1927600/2031616
很明显的看出,当调用System.gc()后,内存真的被回收回来了。
从执行结果中还可以看出,使用掉的内存和回收的内存大小不太一样。这是因为系统中除了我们产生出来的MyObject对象外,我们使用了System类所提供的方法也需要使用内存、GCTest类本身也会用掉一些内存等到。所以当你调用System.gc()时,只要是可以回收的内存都会被回收回来。
实际上,Java在内存回收时是自动进行,对于开发人员来说是透明的。GC在执行时有一定的回收顺序,回收顺序跟对象实例产生的顺序有关。