Java進程監控



 最近項目需要對Java進程,堆棧信息,內存,cpu等資源的消耗進行監控,借鑒了git已有的輪子 JPOM java項目管理系統在線demo網站及對其源碼的分析,提煉出了以下幾種監控方式。

1.引言

 有兩種途徑可以監控Java進程及對應JVM信息:
 一.使用JDK自帶rt.jar中 java.lang.management包下的類來管理。java.lang.management包提供了全面的監控和管理工具,包括JVM的監管API、監管API日志、jconsole和其他監控工具、Java管理擴展平台(JMX)等等。

類名 描述
ClassLoadingMXBean 用於 Java 虛擬機的類加載系統的管理接口。
CompilationMXBean 用於 Java 虛擬機的編譯系統的管理接口。
GarbageCollectorMXBean 用於 Java 虛擬機的垃圾回收的管理接口。
MemoryManagerMXBean 內存管理器的管理接口。
MemoryMXBean Java 虛擬機的內存系統的管理接口。
MemoryPoolMXBean 內存池的管理接口。
OperatingSystemMXBean 用於操作系統的管理接口,Java 虛擬機在此操作系統上運行。
RuntimeMXBean Java 虛擬機的運行時系統的管理接口。
ThreadMXBean Java 虛擬機線程系統的管理接口。

 二 . 使用系統和JVM提供的命令來獲取。
 如導出堆棧信息: jmap -heap 2576 > JVMHeap.log
 進程線程信息:jstack 2576 >> JVMjstack.log
 內存使用情況:

        window: tasklist /V /FI "pid eq 5027"
	linux : top -b -n 1 -p 5027

2. 程序啟停, 為進程自定義項目名稱

  Linux: 啟動命令

String command = String.format("nohup java %s %s -Dapplication=%s -Dbasedir=%s %s %s >> %s 2>&1 &",
        projectInfoModel.getJvm(),
        ProjectInfoModel.getClassPathLib(projectInfoModel),
        projectInfoModel.getId(),
        projectInfoModel.getAbsoluteLib(),
        projectInfoModel.getMainClass(),
        projectInfoModel.getArgs(),
        projectInfoModel.getAbsoluteLog());

 Linux停止

kill  %s

 Window啟動

String command = String.format("javaw %s %s -Dapplication=%s -Dbasedir=%s %s %s >> %s &",
        jvm, classPath, tag,
        projectInfoModel.getAbsoluteLib(), mainClass, args, projectInfoModel.getAbsoluteLog());

 Window停止

taskkill /F /PID %s

tips: -D =value
在虛擬機的系統屬性中設置屬性名/值對,運行在此虛擬機之上的應用程序可用System.getProperty(“propertyName”)得到value的值。如果value中有空格,則需要用雙引號將該值括起來,如-Dname=”space string”。該參數通常用於設置系統級全局變量值,如配置文件路徑,應為該屬性在程序中任何地方都可訪問。

 啟動命令中添加 -Dapplication=%s 參數來將Project Name加入進程的JVM信息中,后續訪問可根據Project Name確定唯一的進程Pid。

Properties properties = virtualMachine.getAgentProperties();
String args = properties.getProperty("sun.jvm.args", "");
if (StrUtil.containsIgnoreCase(args, appTag)) {
    return virtualMachine;
}
args = properties.getProperty("sun.java.command", "");
if (StrUtil.containsIgnoreCase(args, appTag)) {
    return virtualMachine;
}

3. 操作系統判斷

 使用System.getProperties() 來獲取操作系統配置參數: 如System.getProperty("os.name")獲取當前操作系統。

Key Description of Associated Value 中文描述
java.version Java Runtime Environment version Java 運行時環境版本
java.vendor Java Runtime Environment vendor Java 運行時環境供應商
java.vendor.url Java vendor URL Java 供應商的 URL
java.home Java installation directory Java 安裝目錄
java.vm.specification.version Java Virtual Machine specification version Java 虛擬機規范版本
java.vm.specification.vendor Java Virtual Machine specification vendor Java 虛擬機規范供應商
java.vm.specification.name Java Virtual Machine specification name Java 虛擬機規范名稱
java.vm.version Java Virtual Machine implementation version Java 虛擬機實現版本
java.vm.vendor Java Virtual Machine implementation vendor Java 虛擬機實現供應商
java.vm.name Java Virtual Machine implementation name Java 虛擬機實現名稱
java.specification.version Java Runtime Environment specification version Java 運行時環境規范版本
java.specification.vendor Java Runtime Environment specification vendor Java 運行時環境規范供應商
java.specification.name Java Runtime Environment specification name Java 運行時環境規范名稱
java.class.version Java class format version number Java 類格式版本號
java.class.path Java class path Java 類路徑
java.library.path List of paths to search when loading libraries 加載庫時搜索的路徑列表
java.io.tmpdir Default temp file path 默認的臨時文件路徑
java.compiler Name of JIT compiler to use 要使用的 JIT 編譯器的名稱
java.ext.dirs Path of extension directory or directories 一個或多個擴展目錄的路徑
os.name Operating system name 操作系統的名稱
os.arch Operating system architecture 操作系統的架構
os.version Operating system version 操作系統的版本
file.separator File separator ("/" on UNIX) 文件分隔符(在 UNIX 系統中是“/”)
path.separator Path separator (":" on UNIX) 路徑分隔符(在 UNIX 系統中是“:”)
line.separator Line separator ("\n" on UNIX) 行分隔符(在 UNIX 系統中是“/n”)
user.name User's account name 用戶的賬戶名稱
user.home User's home directory 用戶的主目錄
user.dir User's current working directory 用戶的當前工作目錄

 或者使用OperatingSystemMXBean系統類來獲取

OperatingSystemMXBean op = ManagementFactory.getOperatingSystemMXBean();
System.out.println("Architecture: " + op.getArch());
System.out.println("Processors: " + op.getAvailableProcessors());
System.out.println("System name: " + op.getName());
System.out.println("System version: " + op.getVersion());
System.out.println("Last minute load: " + op.getSystemLoadAverage());

4. 獲取進程信息

Window : tasklist /V | findstr java
Linux: top -b -n 1 | grep java

通過 VirtualMachine.list() 取得JVM進程描述信息對象

 List<VirtualMachineDescriptor> descriptorList = VirtualMachine.list();

5. 內存,CPU信息

 Window:
使用命令 tasklist /V /FI "pid eq 5027" 獲得進程的內存使用信息,結合OperatingSystemMXBean獲取操作系統的內存等的使用情況來分析;
 Linux:

	top -b -n 1 -p 5027  

6. 堆內存信息

 使用 MemoryMXBean獲取堆內存和非堆內存(方法區)

MemoryMXBean mem = ManagementFactory.getMemoryMXBean();
//堆內存
MemoryUsage memory = memoryMXBean.getHeapMemoryUsage();
//非堆內存
MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();

7. 端口信息

window: netstat -nao -p tcp | findstr /V "CLOSE_WAIT" | findstr 2576
	linux : netstat -antup | grep  2576 |grep -v "CLOSE_WAIT" | head -20

8. 線程信息

ThreadMXBean thread = ManagementFactory.getThreadMXBean();
System.out.println("ThreadCount: " + thread.getThreadCount());
System.out.println("AllThreadIds: " + thread.getAllThreadIds());
System.out.println("CurrentThreadUserTime: " + thread.getCurrentThreadUserTime());

9. MXBean使用樣例

9.1 根據pid獲取jvm對象

VirtualMachine virtualMachine = VirtualMachine.attach(Integer.toString(pid));

9.2 根據jvm對象獲取jmx服務

    public static JMXServiceURL getJMXServiceURL(VirtualMachine virtualMachine) throws IOException, AgentLoadException, AgentInitializationException {
        String address = virtualMachine.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
        if (address != null) {
            return new JMXServiceURL(address);
        }
        int pid = Convert.toInt(virtualMachine.id());
        address = ConnectorAddressLink.importFrom(pid);
        if (address != null) {
            return new JMXServiceURL(address);
        }
        String agent = getManagementAgent();
        virtualMachine.loadAgent(agent);
        address = virtualMachine.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
        if (address != null) {
            return new JMXServiceURL(address);
        }
        return null;
    }

9.3. 使用MXBean代理獲取具體管理工具

	   /**
     * 訪問指定程序的 MXBean
     */
    public static <T extends PlatformManagedObject> T visitMBean(int pid, Class<T> clazz) throws Exception {
        //第一種直接調用同一 Java 虛擬機內的 MXBean 中的方法。
//        RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
//        String vendor1 = mxbean.getVmVendor();
//        System.out.println("vendor1:" + vendor1);

        //第二種使用 MXBean 代理
        VirtualMachine virtualMachine = VirtualMachine.attach(Integer.toString(pid));
        JMXServiceURL jmxServiceURL = JVMUtil.getJMXServiceURL(virtualMachine);
        if (jmxServiceURL == null) {
            return null;
        }
        JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, null);
        MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
//        return ManagementFactory.newPlatformMXBeanProxy(mBeanServerConnection, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);
//        ManagementFactory.newPlatformMXBeanProxy(mBeanServerConnection, mxBeanName, clazz);
        return ManagementFactory.getPlatformMXBean(mBeanServerConnection, clazz);

    }

    /**
     * 訪問指定程序的 MXBean
     */
    public static <T extends PlatformManagedObject> List<T> visitMBeans(int pid, Class<T> clazz) throws Exception {
        //第一種直接調用同一 Java 虛擬機內的 MXBean 中的方法。
//        RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
//        String vendor1 = mxbean.getVmVendor();
//        System.out.println("vendor1:" + vendor1);

        //第二種使用 MXBean 代理
        VirtualMachine virtualMachine = VirtualMachine.attach(Integer.toString(pid));
        JMXServiceURL jmxServiceURL = JVMUtil.getJMXServiceURL(virtualMachine);
        if (jmxServiceURL == null) {
            return null;
        }
        JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, null);
        MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
        return ManagementFactory.getPlatformMXBeans(mBeanServerConnection, clazz);

    }

9.4 訪問MXBean demo

        ThreadMXBean threadMXBean = (ThreadMXBean) visitMBean(pid, clazz);
        long[] threadIds = threadMXBean.getAllThreadIds();
        System.out.println("ThreadCount: " + threadMXBean.getThreadCount());
        System.out.println("AllThreadIds: " + threadMXBean.getAllThreadIds());
        System.out.println("CurrentThreadUserTime: " + threadMXBean.getCurrentThreadUserTime());
//        for (int i = 0; i < threadIds.length; i++) {
//            ThreadInfo info = threadMXBean.getThreadInfo(threadIds[i]);
//            System.out.println(info);
//        }

        List<GarbageCollectorMXBean> collectorMXBeanList2 = visitMBeans(pid, GarbageCollectorMXBean.class);
        System.out.println(collectorMXBeanList2);
        for(GarbageCollectorMXBean GarbageCollectorMXBean : collectorMXBeanList2){
            System.out.println("gc name:" + GarbageCollectorMXBean.getName());
            System.out.println("CollectionCount:" + GarbageCollectorMXBean.getCollectionCount());
            System.out.println("CollectionTime" + GarbageCollectorMXBean.getCollectionTime());
        }	

9.6 demo

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.management.*;
import java.util.List;

/**
 * java.lang.management包 監控
 */
public class JVMManagementDemo {


    /**
     * {@link ManagementFactory}
     * 	ClassLoadingMXBean	用於 Java 虛擬機的類加載系統的管理接口。
     * 	CompilationMXBean	用於 Java 虛擬機的編譯系統的管理接口。
     * 	GarbageCollectorMXBean	用於 Java 虛擬機的垃圾回收的管理接口。
     * 	MemoryManagerMXBean	內存管理器的管理接口。
     * 	MemoryMXBean	Java 虛擬機的內存系統的管理接口。
     * 	MemoryPoolMXBean	內存池的管理接口。
     * 	OperatingSystemMXBean	用於操作系統的管理接口,Java 虛擬機在此操作系統上運行。
     * 	RuntimeMXBean	Java 虛擬機的運行時系統的管理接口。
     * 	ThreadMXBean	Java 虛擬機線程系統的管理接口。
     *
     *  @cmd
     *  start : javaw -jar -Xms10M -Dapplication=simpleDemo simpleDemo-1.0-SNAPSHOT.jar
     *  stop : taskkill /F /PID 1201
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {

        // 獲取本機信息
        showJvmInfo();
        showMemoryInfo();
        showSystem();
        showClassLoading();
        showCompilation();
        showThread();
        showGarbageCollector();
        showMemoryManager();
        showMemoryPool();

        // 代理獲取 遠程 進程信息
       /* String tag = "simpleDemo";
        int pid = AbstractProjectCommander.getInstance().getPid(tag);*/
       int pid = 12345;
        Class clazz = ThreadMXBean.class;

        ThreadMXBean threadMXBean = (ThreadMXBean) visitMBean(pid, clazz);
        long[] threadIds = threadMXBean.getAllThreadIds();
        System.out.println("ThreadCount: " + threadMXBean.getThreadCount());
        System.out.println("AllThreadIds: " + threadMXBean.getAllThreadIds());
        System.out.println("CurrentThreadUserTime: " + threadMXBean.getCurrentThreadUserTime());
//        for (int i = 0; i < threadIds.length; i++) {
//            ThreadInfo info = threadMXBean.getThreadInfo(threadIds[i]);
//            System.out.println(info);
//        }

        List<GarbageCollectorMXBean> collectorMXBeanList2 = visitMBeans(pid, GarbageCollectorMXBean.class);
        System.out.println(collectorMXBeanList2);
        for(GarbageCollectorMXBean GarbageCollectorMXBean : collectorMXBeanList2){
            System.out.println("gc name:" + GarbageCollectorMXBean.getName());
            System.out.println("CollectionCount:" + GarbageCollectorMXBean.getCollectionCount());
            System.out.println("CollectionTime" + GarbageCollectorMXBean.getCollectionTime());
        }

    }

    /**
     * Java 虛擬機的運行時系統
     */
    public static void showJvmInfo() {
        RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
        String vendor = mxbean.getVmVendor();
        System.out.println("jvm name:" + mxbean.getVmName());
        System.out.println("jvm version:" + mxbean.getVmVersion());
        System.out.println("jvm bootClassPath:" + mxbean.getBootClassPath());
        System.out.println("jvm start time:" + mxbean.getStartTime());
    }

    /**
     * Java 虛擬機的內存系統
     */
    public static void showMemoryInfo() {
        MemoryMXBean mem = ManagementFactory.getMemoryMXBean();
        MemoryUsage heap = mem.getHeapMemoryUsage();
        System.out.println("Heap committed:" + heap.getCommitted() + " init:" + heap.getInit() + " max:"
                + heap.getMax() + " used:" + heap.getUsed());
    }

    /**
     * Java 虛擬機在其上運行的操作系統
     */
    public static void showSystem() {
        OperatingSystemMXBean op = ManagementFactory.getOperatingSystemMXBean();
        System.out.println("Architecture: " + op.getArch());
        System.out.println("Processors: " + op.getAvailableProcessors());
        System.out.println("System name: " + op.getName());
        System.out.println("System version: " + op.getVersion());
        System.out.println("Last minute load: " + op.getSystemLoadAverage());
    }

    /**
     * Java 虛擬機的類加載系統
     */
    public static void showClassLoading(){
        ClassLoadingMXBean cl = ManagementFactory.getClassLoadingMXBean();
        System.out.println("TotalLoadedClassCount: " + cl.getTotalLoadedClassCount());
        System.out.println("LoadedClassCount" + cl.getLoadedClassCount());
        System.out.println("UnloadedClassCount:" + cl.getUnloadedClassCount());
    }

    /**
     * Java 虛擬機的編譯系統
     */
    public static void showCompilation(){
        CompilationMXBean com = ManagementFactory.getCompilationMXBean();
        System.out.println("TotalCompilationTime:" + com.getTotalCompilationTime());
        System.out.println("name:" + com.getName());
    }

    /**
     * Java 虛擬機的線程系統
     */
    public static void showThread(){
        ThreadMXBean thread = ManagementFactory.getThreadMXBean();
        System.out.println("ThreadCount: " + thread.getThreadCount());
        System.out.println("AllThreadIds: " + thread.getAllThreadIds());
        System.out.println("CurrentThreadUserTime: " + thread.getCurrentThreadUserTime());
        //......還有其他很多信息
    }

    /**
     * Java 虛擬機中的垃圾回收器。
     */
    public static void showGarbageCollector(){
        List<GarbageCollectorMXBean> gc = ManagementFactory.getGarbageCollectorMXBeans();
        for(GarbageCollectorMXBean GarbageCollectorMXBean : gc){
            System.out.println("GC name:" + GarbageCollectorMXBean.getName());
            System.out.println("CollectionCount:" + GarbageCollectorMXBean.getCollectionCount());
            System.out.println("CollectionTime" + GarbageCollectorMXBean.getCollectionTime());
        }
    }

    /**
     * Java 虛擬機中的內存管理器
     */
    public static void showMemoryManager(){
        List<MemoryManagerMXBean> mm = ManagementFactory.getMemoryManagerMXBeans();
        for(MemoryManagerMXBean eachmm: mm){
            System.out.println("name:" + eachmm.getName());
            System.out.println("MemoryPoolNames:" + eachmm.getMemoryPoolNames().toString());
        }
    }

    /**
     * Java 虛擬機中的內存池
     */
    public static void showMemoryPool(){
        List<MemoryPoolMXBean> mps = ManagementFactory.getMemoryPoolMXBeans();
        for(MemoryPoolMXBean mp : mps){
            System.out.println("name:" + mp.getName());
            System.out.println("CollectionUsage:" + mp.getCollectionUsage());
            System.out.println("type:" + mp.getType());
        }
    }

    /**
     * 訪問指定程序的 MXBean
     */
    public static <T extends PlatformManagedObject> T visitMBean(int pid, Class<T> clazz) throws Exception {
        //第一種直接調用同一 Java 虛擬機內的 MXBean 中的方法。
//        RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
//        String vendor1 = mxbean.getVmVendor();
//        System.out.println("vendor1:" + vendor1);

        //第二種使用 MXBean 代理
        VirtualMachine virtualMachine = VirtualMachine.attach(Integer.toString(pid));
        JMXServiceURL jmxServiceURL = JVMUtil.getJMXServiceURL(virtualMachine);
        if (jmxServiceURL == null) {
            return null;
        }
        JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, null);
        MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
//        return ManagementFactory.newPlatformMXBeanProxy(mBeanServerConnection, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);
//        ManagementFactory.newPlatformMXBeanProxy(mBeanServerConnection, mxBeanName, clazz);
        return ManagementFactory.getPlatformMXBean(mBeanServerConnection, clazz);

    }

    /**
     * 訪問指定程序的 MXBean
     */
    public static <T extends PlatformManagedObject> List<T> visitMBeans(int pid, Class<T> clazz) throws Exception {
        //第一種直接調用同一 Java 虛擬機內的 MXBean 中的方法。
//        RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
//        String vendor1 = mxbean.getVmVendor();
//        System.out.println("vendor1:" + vendor1);

        //第二種使用 MXBean 代理
        VirtualMachine virtualMachine = VirtualMachine.attach(Integer.toString(pid));
        JMXServiceURL jmxServiceURL = JVMUtil.getJMXServiceURL(virtualMachine);
        if (jmxServiceURL == null) {
            return null;
        }
        JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, null);
        MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
        return ManagementFactory.getPlatformMXBeans(mBeanServerConnection, clazz);

    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM