如何通过JAVA代码获取JVM相关信息

最近一直在排查JVM内存问题,所以对该方面进行了一定的整理,我们可以通过ManagementFactory可以获取当前JVM的相关运行信息,对应用进行监控。

下面的代码一部分网上整理(太懒,别人有的干嘛自己写的),一部分自己查看API获取,希望对大家工作有所帮助,JVM的相关知识就不再赘述了。

import java.lang.management.ClassLoadingMXBean;
import java.lang.management.CompilationMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;

public class HeapMain {

	private static NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH));
    private static NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH));

	public static void main(String[] args) {
		//运行时情况
		RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
		//操作系统情况
        OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
        //线程使用情况
        ThreadMXBean threads = ManagementFactory.getThreadMXBean();
        //堆内存使用情况
        MemoryUsage heapMemoryUsage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
        //非堆内存使用情况
        MemoryUsage nonHeapMemoryUsage = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();
        //类加载情况
        ClassLoadingMXBean cl = ManagementFactory.getClassLoadingMXBean();
        //内存池对象
        List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
        //编译器和编译情况
        CompilationMXBean cm = ManagementFactory.getCompilationMXBean();
        //获取GC对象(不好用)
        List<GarbageCollectorMXBean> gcmList = ManagementFactory.getGarbageCollectorMXBeans();
        
        
       
        //运行时情况
        System.out.printf("jvm.name (JVM名称-版本号-供应商):%s | version: %s | vendor: %s  %n", runtime.getVmName(), runtime.getVmVersion(), runtime.getVmVendor());
        System.out.printf("jvm.spec.name (JVM规范名称-版本号-供应商):%s | version: %s | vendor: %s  %n", runtime.getSpecName(), runtime.getSpecVersion(), runtime.getSpecVendor());
        System.out.printf("jvm.java.version (JVM JAVA版本):%s%n", System.getProperty("java.version"));
        System.out.printf("jvm.start.time (Java虚拟机的启动时间):%s%n", toDuration(runtime.getStartTime()));
        System.out.printf("jvm.uptime (Java虚拟机的正常运行时间):%s%n", toDuration(runtime.getUptime()));
       
        System.out.println("------------------------------------------------------------------------------------------------------");
        
        //编译情况
        System.out.printf("compilation.name(编译器名称):%s%n",cm.getName());
        System.out.printf("compilation.total.time(编译器耗时):%d毫秒%n",cm.getTotalCompilationTime());
        boolean isSupport=cm.isCompilationTimeMonitoringSupported();  
        if(isSupport){  
            System.out.println("支持即时编译器编译监控");  
        }else{  
            System.out.println("不支持即时编译器编译监控");  
        }  
        System.out.printf("------------------------------------------------------------------------------------------------------");
        //JVM 线程情况
        System.out.printf("jvm.threads.total.count (总线程数(守护+非守护)):%d%n", threads.getThreadCount());
        System.out.printf("jvm.threads.daemon.count (守护进程线程数):%d%n", threads.getDaemonThreadCount());
        System.out.printf("jvm.threads.peak.count (峰值线程数):%d%n", threads.getPeakThreadCount());
        System.out.printf("jvm.threads.total.start.count(Java虚拟机启动后创建并启动的线程总数):%d%n", threads.getTotalStartedThreadCount());
        for(Long threadId : threads.getAllThreadIds()) {
        	System.out.printf("threadId: %d | threadName: %s%n", threadId, threads.getThreadInfo(threadId).getThreadName());
        }
        System.out.println("------------------------------------------------------------------------------------------------------");
        //获取GC信息
        
        System.out.println("------------------------------------------------------------------------------------------------------");
        //堆内存情况
        System.out.printf("jvm.heap.init (初始化堆内存):%s %n",  bytesToMB(heapMemoryUsage.getInit()));
        System.out.printf("jvm.heap.used (已使用堆内存):%s %n", bytesToMB(heapMemoryUsage.getUsed()));
        System.out.printf("jvm.heap.committed (可使用堆内存):%s %n", bytesToMB(heapMemoryUsage.getCommitted()));
        System.out.printf("jvm.heap.max (最大堆内存):%s %n", bytesToMB(heapMemoryUsage.getMax()));
       
        System.out.println("------------------------------------------------------------------------------------------------------");
       
        //非堆内存使用情况
        System.out.printf("jvm.noheap.init (初始化非堆内存):%s %n",  bytesToMB(nonHeapMemoryUsage.getInit()));
        System.out.printf("jvm.noheap.used (已使用非堆内存):%s %n",  bytesToMB(nonHeapMemoryUsage.getUsed()));
        System.out.printf("jvm.noheap.committed (可使用非堆内存):%s %n",  bytesToMB(nonHeapMemoryUsage.getCommitted()));
        System.out.printf("jvm.noheap.max (最大非堆内存):%s %n", bytesToMB(nonHeapMemoryUsage.getMax()));
       
        System.out.println("------------------------------------------------------------------------------------------------------");
       
        //系统概况
        System.out.printf("os.name(操作系统名称-版本号):%s %s %s %n", os.getName(), "version", os.getVersion());
        System.out.printf("os.arch(操作系统内核):%s%n", os.getArch());
        System.out.printf("os.cores(可用的处理器数量):%s %n", os.getAvailableProcessors());
        System.out.printf("os.loadAverage(系统负载平均值):%s %n", os.getSystemLoadAverage());
       
        System.out.println("------------------------------------------------------------------------------------------------------");
       
        //类加载情况
        System.out.printf("class.current.load.count(当前加载类数量):%s %n", cl.getLoadedClassCount());
        System.out.printf("class.unload.count(未加载类数量):%s %n", cl.getUnloadedClassCount());
        System.out.printf("class.total.load.count(总加载类数量):%s %n", cl.getTotalLoadedClassCount());
       
        System.out.println("------------------------------------------------------------------------------------------------------");

        for(MemoryPoolMXBean pool : pools) {
        	final String kind = pool.getType().name(); 
        	final MemoryUsage usage = pool.getUsage(); 
        	System.out.println("内存模型: " + getKindName(kind) + ", 内存空间名称: " + getPoolName(pool.getName()) + ", jvm." + pool.getName() + ".init(初始化):" + bytesToMB(usage.getInit())); 
        	System.out.println("内存模型: " + getKindName(kind) + ", 内存空间名称: " + getPoolName(pool.getName()) + ", jvm." + pool.getName() + ".used(已使用): " + bytesToMB(usage.getUsed())); 
        	System.out.println("内存模型: " + getKindName(kind) + ", 内存空间名称: " + getPoolName(pool.getName()) + ", jvm." + pool.getName()+ ".committed(可使用):" + bytesToMB(usage.getCommitted())); 
        	System.out.println("内存模型: " + getKindName(kind) + ", 内存空间名称: " + getPoolName(pool.getName()) + ", jvm." + pool.getName() + ".max(最大):" + bytesToMB(usage.getMax()));
        	System.out.println("------------------------------------------------------------------------------------------------------");
        }
       
	}
	
	protected static String getKindName(String kind) {
		if("NON_HEAP".equals(kind)) {
			return "NON_HEAP(非堆内存)";
		}else {
			return "HEAP(堆内存)";
		}
	}
	
	protected static String getPoolName(String poolName) {
		switch (poolName) {
			case "Code Cache":
				return poolName +"(代码缓存区)";
			case "Metaspace":
				return poolName +"(元空间)";
			case "Compressed Class Space":
				return poolName +"(类指针压缩空间)";
			case "PS Eden Space":
				return poolName +"(伊甸园区)";
			case "PS Survivor Space":
				return poolName +"(幸存者区)";
			case "PS Old Gen":
				return poolName +"(老年代)";
			default:
				return poolName;
		}
	}
	
	
	protected static String bytesToMB(long bytes) {
		return fmtI.format((long)(bytes / 1024 / 1024)) + " MB";
	}
	
	protected static String printSizeInKb(double size) {
        return fmtI.format((long) (size / 1024)) + " kbytes";
    }

    protected static String toDuration(double uptime) {
        uptime /= 1000;
        if (uptime < 60) {
            return fmtD.format(uptime) + " seconds";
        }
        uptime /= 60;
        if (uptime < 60) {
            long minutes = (long) uptime;
            String s = fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
            return s;
        }
        uptime /= 60;
        if (uptime < 24) {
            long hours = (long) uptime;
            long minutes = (long) ((uptime - hours) * 60);
            String s = fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
            if (minutes != 0) {
                s += " " + fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
            }
            return s;
        }
        uptime /= 24;
        long days = (long) uptime;
        long hours = (long) ((uptime - days) * 24);
        String s = fmtI.format(days) + (days > 1 ? " days" : " day");
        if (hours != 0) {
            s += " " + fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
        }
        return s;
    }

}
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
你可以使用以下代码获取指定端口号的 JVM,并输出 GC 信息: ```java import com.sun.management.GarbageCollectionNotificationInfo; import com.sun.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.List; import java.util.Map; public class GCDemo { public static void main(String[] args) throws UnknownHostException { // 获取当前运行的 JVM 的 PID RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); String name = runtime.getName(); // format: "pid@hostname" int pid = Integer.parseInt(name.substring(0, name.indexOf('@'))); // 获取当前主机的 IP 地址 InetAddress inetAddress = InetAddress.getLocalHost(); String ipAddress = inetAddress.getHostAddress(); // 获取指定端口号对应的 JVM 的 PID int port = 8080; // 指定端口号 List<RuntimeMXBean> runtimeMXBeans = ManagementFactory.getRuntimeMXBeans(); int remotePid = -1; for (RuntimeMXBean runtimeMXBean : runtimeMXBeans) { Map<String, String> systemProperties = runtimeMXBean.getSystemProperties(); String address = systemProperties.get("sun.management.jmxremote.localAddress"); if (address != null && address.contains(ipAddress) && address.contains(":" + port)) { remotePid = Integer.parseInt(runtimeMXBean.getName().split("@")[0]); break; } } if (remotePid == -1) { System.out.println("没有找到对应端口号的 JVM"); return; } if (remotePid != pid) { System.out.println("指定端口号对应的 JVM 不是当前运行的 JVM"); return; } // 找到 GC MXBean 并注册监听器 List<GarbageCollectorMXBean> gcMXBeans = ManagementFactory.getGarbageCollectorMXBeans(); for (GarbageCollectorMXBean gcMXBean : gcMXBeans) { System.out.println("GC Name: " + gcMXBean.getName()); gcMXBean.addGarbageCollectionNotificationListener( (notification, handback) -> { GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo.from(notification); System.out.println("GC Name: " + info.getGcName()); System.out.println("GC Action: " + info.getGcAction()); System.out.println("GC Cause: " + info.getGcCause()); System.out.println("Start Time: " + info.getGcInfo().getStartTime()); System.out.println("Duration: " + info.getGcInfo().getDuration() + " ms"); System.out.println("Memory Usage After GC:"); Map<String, MemoryUsage> memoryUsageAfterGc = info.getGcInfo().getMemoryUsageAfterGc(); for (Map.Entry<String, MemoryUsage> entry : memoryUsageAfterGc.entrySet()) { System.out.println(" " + entry.getKey() + ": " + entry.getValue()); } }, null); } } } ``` 代码中主要分为以下几个步骤: 1. 获取当前运行的 JVM 的 PID; 2. 获取当前主机的 IP 地址; 3. 遍历所有运行的 JVM,找到指定端口号对应的 JVM 的 PID; 4. 如果没有找到对应端口号的 JVM 或者对应的 JVM 不是当前运行的 JVM,则退出; 5. 找到所有 GC MXBean 并注册监听器,输出 GC 信息。 注意:这段代码使用了 JDK 私有 API,如果你想要在生产环境中使用,请自行替换为公开 API。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值