OracleJvisualVM的施用【转载】

VisualVM 是平等慢性免费之,集成了大多单 JDK
命令行工具的可视化工具,它能啊您提供有力的剖析能力,对 Java
应用程序做性能分析以及调优。这些作用包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和
CPU 分析,同时其还支持以 MBeans 上进展浏览以及操作。本文主要介绍如何利用
VisualVM 拓展性分析以及调优。

起 JDK 6 Update 7 以后都作 Oracle JDK 的一模一样组成部分,位于 JDK 根目录的
bin 文件夹下,无需安装,直接运行即可。

 

VisualVM 通过检测 JVM
中加载的接近和对象信息等辅助我们解析内存以状况,我们可通过 VisualVM
的监标签对应用程序进行内存分析。

1)内存堆Heap

率先我们来拘禁内存堆Heap使用状态,我本机eclipse的长河在visualVM显示如下:

Oracle 1

 

无论写个小序占用内存大的,运行一下

次如下:

Oracle 2

Oracle 3

package jvisualVM;

public class JavaHeapTest {
    public final static int OUTOFMEMORY = 200000000;

    private String oom;

    private int length;

    StringBuffer tempOOM = new StringBuffer();

    public JavaHeapTest(int leng) {
        this.length = leng;

        int i = 0;
        while (i < leng) {
            i++;
            try {
                tempOOM.append("a");
            } catch (OutOfMemoryError e) {
               e.printStackTrace();
               break;
            }
        }
        this.oom = tempOOM.toString();

    }

    public String getOom() {
        return oom;
    }

    public int getLength() {
        return length;
    }

    public static void main(String[] args) {
        JavaHeapTest javaHeapTest = new JavaHeapTest(OUTOFMEMORY);
        System.out.println(javaHeapTest.getOom().length());
    }

}

Oracle 4

Oracle 5

查看VisualVM Monitor tab, 堆内存变大了

Oracle 6

 

在程序运行结束之前, 点击Heap Dump 按钮,
等待一会儿,得到dump结果,可以看看部分Summary信息

点击Classes, 发现char[]所占据的内存是极其深的

Oracle 7

 

双击它,得到如下Instances结果

Oracle 8

 Instances是以Size由老及有些排列的

先是个就是无与伦比深的, 展开Field区域的 values

Oracle 9

StringBuffer类型的 全局变量 tempOOM 占用内存特别坏,
注意有变量是无法通过 堆dump来得到解析结果的。

此外,对于“堆
dump”来说,在远距离监控jvm的时光,VisualVM是从未这效应的,只有本地监控之上才产生。

 

2)永久保存区域PermGen

副来拘禁下永久保存区域PermGen使用状况

运作一段子类加载的次序,代码如下:

Oracle 10

Oracle 11

package jvisualVM;

import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

public class TestPermGen {

    private static List<Object> insList = new ArrayList<Object>();

    public static void main(String[] args) throws Exception {

        permLeak();
    }

    private static void permLeak() throws Exception {
        for (int i = 0; i < 1000; i++) {
            URL[] urls = getURLS();
            URLClassLoader urlClassloader = new URLClassLoader(urls, null);
            Class<?> logfClass = Class.forName("org.apache.commons.logging.LogFactory", true,urlClassloader);
            Method getLog = logfClass.getMethod("getLog", String.class);
            Object result = getLog.invoke(logfClass, "TestPermGen");
            insList.add(result);
            System.out.println(i + ": " + result);
        }
    }

    private static URL[] getURLS() throws MalformedURLException {
        File libDir = new File("C:/Users/wadexu/.m2/repository/commons-logging/commons-logging/1.1.1");
        File[] subFiles = libDir.listFiles();
        int count = subFiles.length;
        URL[] urls = new URL[count];
        for (int i = 0; i < count; i++) {
            urls[i] = subFiles[i].toURI().toURL();
        }
        return urls;
    }


}

Oracle 12

Oracle 13

一个种类装载之后会创造一个相应的java.lang.Class实例,这个实例本身以及一般对象实例一样存储于堆着,我认为之所以说凡是即时是平等栽特殊之实例,某种程度上是为其当了走访PermGen区域中类型信息的代理者。

 

运转一段时间后抛OutOfMemoryError了, VisualVM监控结果如下:

Oracle 14

 

敲定:PermGen区域分配的积聚空间了多少,我们好透过安装-XX:
PermSize参数与-XX:MaxPermSize参数来解决。

关于PermGen
OOM深入解析请参考http://www.cnblogs.com/zhuxing/articles/1247621.html

关于Perform GC,
请参考随即篇文章

当即有知识或比尖锐之,有空还要延续研究。

 

CPU
性能分析的要目的是统计函数的调用情况及实施时间,或者另行简便的场面便是统计应用程序的
CPU 使用状况。

并未程序运行时之 CPU 使用情况如下图:

Oracle 15

 

运行一段子 占用CPU 的有些程序,代码如下

Oracle 16

Oracle 17

package jvisualVM;

public class MemoryCpuTest {

    public static void main(String[] args) throws InterruptedException {

        cpuFix();
    }


    /**
     * cpu 运行固定百分比
     * 
     * @throws InterruptedException
     */
    public static void cpuFix() throws InterruptedException {
        // 80%的占有率
        int busyTime = 8;
        // 20%的占有率
        int idelTime = 2;
        // 开始时间
        long startTime = 0;

        while (true) {
            // 开始时间
            startTime = System.currentTimeMillis();

            /*
             * 运行时间
             */
            while (System.currentTimeMillis() - startTime < busyTime) {
                ;
            }

            // 休息时间
            Thread.sleep(idelTime);
        }
    }
}

Oracle 18

Oracle 19

翻监视页面 Monitor tab

Oracle 20

 

过大之 CPU 使用率可能是由于我们的种被在低效的代码;

于咱们对程序予以压的早晚,过小之 CPU 使用率为发出或是程序的题目。

 

点击取样器Sampler, 点击“CPU”按钮, 启动CPU性能分析会话,VisualVM
会检测应用程序所有的让调用的方式,

于CPU samples tab 下得以视我们的办法cpufix() 的私用时间最丰富, 如下图:

Oracle 21

切换至Thread CPU Time 页面下,我们的 main 函数这个过程 占用CPU时间太丰富,
如下图:

Oracle 22

 

 

线程分析篇

JavaOracle
语言会生好之落实多线程应用程序。当我们针对一个多线程应用程序进行调节要开发后期做性能调优的当儿,往往得了解当前程序中有线程的运转状态,是否出死锁、热锁等情景的发,从而分析系统或有的题材。

在 VisualVM 的监标签内,我们得查时应用程序中具备移动线程(Live
threads)和医护线程(Daemon threads)的数额相等实时信息。

 

运行一段小程序,代码如下:

Oracle 23

Oracle 24

package jvisualVM;

public class MyThread extends Thread{

    public static void main(String[] args) {

        MyThread mt1 = new MyThread("Thread a");
        MyThread mt2 = new MyThread("Thread b");

        mt1.setName("My-Thread-1 ");
        mt2.setName("My-Thread-2 ");

        mt1.start();
        mt2.start();
    }

    public MyThread(String name) {
    }

    public void run() {

        while (true) {

        }
    }


}

Oracle 25

Oracle 26

 

Live threads 于11日增有限个 变成13了

Daemon threads从8充实有限只 变成10了 

Oracle 27

 

VisualVM 的线程标签提供了三栽视图,默认会以时间线之点子呈现, 如下图:

可以看出零星个我们run的次序里开始的线程:My-Thread-1 和 My-Thread-2

Oracle 28

 

除此以外还有个别种植视图分别是表视图和详细信息视图,
这里关押一下每个Thread的详尽视图:

Oracle 29

 

 

再度来同样段落死锁的主次,看VisualVM 能否分析出来

Oracle 30

Oracle 31

package jvisualVM;

public class DeadLock {
    public static void main(String[] args) {
        Resource r1 = new Resource();
        Resource r0 = new Resource();

        Thread myTh1 = new LockThread1(r1, r0);
        Thread myTh0 = new LockThread0(r1, r0);

        myTh1.setName("DeadLock-1 ");
        myTh0.setName("DeadLock-0 ");

        myTh1.start();
        myTh0.start();
    }
}

    class Resource {
        private int i;

        public int getI() {
            return i;
        }

        public void setI(int i) {
            this.i = i;
        }

    }

    class LockThread1 extends Thread {
        private Resource r1, r2;

        public LockThread1(Resource r1, Resource r2) {
            this.r1 = r1;
            this.r2 = r2;
        }

        @Override
        public void run() {
            int j = 0;
            while (true) {
                synchronized (r1) {
                    System.out.println("The first thread got r1's lock " + j);
                    synchronized (r2) {
                        System.out.println("The first thread got r2's lock  " + j);
                    }
                }
                j++;
            }
        }

    }

    class LockThread0 extends Thread {
        private Resource r1, r2;

        public LockThread0(Resource r1, Resource r2) {
            this.r1 = r1;
            this.r2 = r2;
        }

        @Override
        public void run() {
            int j = 0;
            while (true) {
                synchronized (r2) {
                    System.out.println("The second thread got r2's lock  " + j);
                    synchronized (r1) {
                        System.out.println("The second thread got r1's lock" + j);
                    }
                }
                j++;
            }
        }

    }

Oracle 32

Oracle 33

 

开辟VisualVM检测及之JVM进程,我们得以看到此tab在闪,VisualVM已经检测及本人者package下面的DeadLock类出错了

切换至Thread tab, 可以见见死锁了, Deadlock detected!

此外可以点击Thread Dump
线程转储,进一步分析,在此处就非赘述了,有趣味之读者可以自动实验。

 Oracle 34

 

相关文章