闲来无事,写了一个小demo来观察jvm中的线程和GC过程,代码如下
public class MyExecutor { public static void main(String[] args) { try { Thread.sleep(15000);//留点时间连接jconsole } catch (InterruptedException e) { e.printStackTrace(); } ExecutorService executorService = Executors.newFixedThreadPool(1); for (int i = 0; i < 10; i++) { executorService.execute(new MyRunnable()); } } }
public class MyRunnable implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "-" + this.hashCode() + ":run"); } @Override protected void finalize() throws Throwable { super.finalize(); System.err.println(Thread.currentThread().getName() + "-" + this.hashCode() + ":finalize"); } }
jvm中的对象在被回收之前会执行finalize()方法。运行以上代码中的main方法,启动jconsole并连接到对应的jvm。
eclipse中的执行情况如下图
由图可见,线程池中只新创建了一个线程,for循环中创建了10个MyRunnable对象。线程执行完任务之后,10个对象并没有立即被回收。此时在jconsole中观察内存使用情况发现内存充足,于是在jconsole中手动触发一次GC,如下图
可见一次GC之后,堆内存使用量明显减少,之后又逐渐上升。此时eclipse控制台打印出了finalize()方法中的内容,如下图:
可见,之前10个未被回收的对象在此次GC中被回收了。