垃圾回收器的实现:
1.让用户都暂停,不再产生垃圾,就去收集垃圾。新生代用复制算法清理垃圾,老生代用标记整理算法搜集垃圾。
优秀的算法:服务端默认是CMS收集器。
%.1.jvm案例演示 内存: Jconsole的内存标签相当于可视化的jstat命令,用于监视收集器管理的虚拟机内存(java堆和永久代)的变化趋势。 我们通过下面的一段代码体验一下它的监视功能。运行时设置的虚拟机参数为:-Xms100m -Xmx100m -XX:+UseSerialGC,这段代码的作用是以64kb/50毫秒的速度往java堆内存中填充数据。 public class TestMemory { static class OOMObject { public byte[] placeholder = new byte[64 * 1024]; } public static void fillHeap(int num) throws Exception { ArrayList<OOMObject> list = new ArrayList<OOMObject>(); for (int i = 0; i < num; i++) { Thread.sleep(50); list.add(new OOMObject()); } System.gc(); } public static void main(String[] args) throws Exception { fillHeap(1000); Thread.sleep(500000); } }
从图中可以看出,运行轨迹成曲线增长,循环1000次后,虽然整个新生代Eden和Survivor区都基本上被清空了,但是老年代仍然保持峰值状态,这说明,填充的数据在GC后仍然存活,因为list的作用域没有结束。如果把System.gc();移到fillHeap(1000);后,就可以全部回收掉。 线程: jconsole线程标签相当于可视化了jstack命令,遇到线程停顿时,可以使用这个也签进行监控分析。线程长时间停顿的主要原因有:等待外部资源(数据库连接等),死循环、锁等待。下面的代码将演示这几种情况: package cn.java.jvm; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class TestThread { /** * 死循环演示 * * @param args */ public static void createBusyThread() { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("createBusyThread"); while (true) ; } }, "testBusyThread"); thread.start(); } /** * 线程锁等待 * * @param args */ public static void createLockThread(final Object lock) { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("createLockThread"); synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "testLockThread"); thread.start(); } public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); br.readLine(); createBusyThread(); br.readLine(); Object object = new Object(); createLockThread(object); } }
main线程:追踪到需要键盘录入 testBusyThread线程:线程阻塞在18行的while(true),直到线程切换,很耗性能 testLockThread线程:出于waitting状态,等待notify 死锁: package cn.java.jvm; public class TestDeadThread implements Runnable { int a, b; public TestDeadThread(int a, int b) { this.a = a; this.b = b; } @Override public void run() { System.out.println("createDeadThread"); synchronized (Integer.valueOf(a)) { synchronized (Integer.valueOf(b)) { System.out.println(a + b); } } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(new TestDeadThread(1, 2)).start(); new Thread(new TestDeadThread(2, 1)).start(); } } }
Jconsole点击检查死锁,会出现死锁的详情。
thread-5的锁被thread-10持有,相反亦是,造成死锁。