jvm2

 垃圾回收器的实现:

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持有,相反亦是,造成死锁。

 

posted @ 2018-05-26 21:53  无天666  阅读(302)  评论(0编辑  收藏  举报