java监控并记录jvm运行时内存、线程、垃圾收集和堆空间

为了及时了解java进程运行时的内存、线程、垃圾收集以及堆空间和操作系统的内存情况,在代码中使用一个单独的线程,将相关信息记录下来,并且循环写入文件中。这样一来,即使java进程被杀掉,在java进程结束前的运行时状态信息也已经持久化到文件中了。

虽然进程启动时,已经设置了内存空间溢出时进行堆dump,但是如果此时整个操作系统的空间太小,而对空间有比较大的情况下,也容易导致堆dump失败。

总之,在缺乏完善的监控机制前提下,适时将程序的运行时信息记录到文件中,出现意外终止时,有助于帮助分析可能原因,以便为后续规避此类问题提供帮助。

package com.demo;

import com.sun.management.OperatingSystemMXBean;

import java.io.File;
import java.io.FileOutputStream;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;

import java.lang.management.ThreadMXBean;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class JVMRuntimeInfoDemo {

    private static String timeMinutes;

    private static ArrayList<String> buff;

    private static Long index = 1l;

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

        LinkedList<String> queue = new LinkedList<String>();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdfMinutes = new SimpleDateFormat("yyyyMMdd-HHmmss");

        Long time = System.currentTimeMillis();

        timeMinutes = sdfMinutes.format(time);

        buff = new ArrayList<>(1024);

        for (int i = 0; i < 60; i++) {
            byte[] bytes = new byte[1024000];

            buff.add(bytes.toString());

            String dateTime = sdf.format(System.currentTimeMillis());

            saveRuntimeInfo(queue);

            Thread.sleep(3000);
        }
    }

    public static void saveRuntimeInfo(LinkedList<String> queue) {

        String fileName = "runtime" + timeMinutes + ".log";
        String filePath = getConfFile(fileName);

        try {

            File confFile = new File(filePath);
            if (!confFile.exists()) {
                confFile.createNewFile();
            }

            FileOutputStream outputStream = new FileOutputStream(confFile);

            String configInfo = "";

            // 记录操作系统内存
            configInfo = getOSMemoryInfo(configInfo);

            // 记录虚拟机内存
            configInfo = getJVMMemoryInfo(configInfo);

            // 堆内存信息
            configInfo = getHeapInfo(configInfo);

            // 垃圾收集信息
            configInfo = getGCInfo(configInfo);

            // 线程信息
            configInfo = getThreadInfo(configInfo);

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            String dateTime = sdf.format(System.currentTimeMillis());

            // String poll = queue.poll();
            configInfo += "\n" + index + " " + dateTime + "\n\n";

            index = index + 1;

            if (index >= 100) {
                index = 1l;
            }

            System.out.println(configInfo);

            queue.addLast(configInfo);

            while (queue.size() > 30) {
                queue.removeFirst();
            }

            // 遍历
            for (String poll : queue) {
                outputStream.write(poll.getBytes(StandardCharsets.UTF_8));
            }

            outputStream.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 获取日志文件路径
    public static String getConfFile(String fileName) {
        URL resource1 = JVMRuntimeInfoDemo.class.getResource("/");

        String path = resource1.getPath();

        int endPos = path.indexOf(".jar!");
        if (endPos > 0)
            path = path.substring(0, endPos);

        endPos = path.lastIndexOf("/");
        if (path.startsWith("file:/"))
            path = path.substring(6, endPos);
        else if (path.startsWith("/"))
            path = path.substring(1, endPos);

        path = path + "/" + fileName;

        return path;
    }

    public static String getOSMemoryInfo(String baseInfo) {
        int byteToMb = 1024 * 1024;

        // 操作系统级内存情况查询
        OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
        String os = System.getProperty("os.name");
        long physicalFree = osmxb.getFreePhysicalMemorySize() / byteToMb;
        long physicalTotal = osmxb.getTotalPhysicalMemorySize() / byteToMb;
        long physicalUse = physicalTotal - physicalFree;

        baseInfo = baseInfo + "\n======操作系统内存信息=======";

        baseInfo = baseInfo + "\n操作系统的版本:" + os;

        baseInfo = baseInfo + "\n操作系统内存已使用:" + physicalFree + " MB";

        baseInfo = baseInfo + "\n操作系统内存剩余:" + physicalUse + " MB";

        baseInfo = baseInfo + "\n操作系统总内存:" + physicalTotal + " MB";

        return baseInfo;
    }

    public static String getJVMMemoryInfo(String baseInfo) {
        // 虚拟机级内存情况查询
        long vmFree = 0;
        long vmUse = 0;
        long vmTotal = 0;
        long vmMax = 0;
        int byteToMb = 1024 * 1024;
        Runtime rt = Runtime.getRuntime();
        vmTotal = rt.totalMemory() / byteToMb;
        vmFree = rt.freeMemory() / byteToMb;
        vmMax = rt.maxMemory() / byteToMb;
        vmUse = vmTotal - vmFree;

        baseInfo = baseInfo + "\n======JVM内存信息=======";
        baseInfo += "\nJVM内存已用的空间为:" + vmUse + " MB";
        baseInfo += "\n" + "JVM内存的空闲空间为:" + vmFree + " MB";
        // jvm当前分配空间
        baseInfo += "\n" + "JVM总内总存空间为:" + vmTotal + " MB";
        // 与jvm配置有关
        baseInfo += "\n" + "JVM总内存最大空间为:" + vmMax + " MB";

        return baseInfo;
    }

    // 堆空间信息
    public static String getHeapInfo(String baseInfo) {
        int byteToMb = 1024 * 1024;

        MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean();
        MemoryUsage usage = memorymbean.getHeapMemoryUsage();

        baseInfo = baseInfo + "\n======堆内存信息=======";

        baseInfo += "\n初始堆大小:" + usage.getInit() / byteToMb + "MB";
        baseInfo += "\n最大值:" + usage.getMax() / byteToMb + "MB";
        baseInfo += "\n已使用:" + usage.getUsed() / byteToMb + "MB";

        return baseInfo;
    }

    // 垃圾收集信息
    public static String getGCInfo(String baseInfo) {
        List<GarbageCollectorMXBean> gcmList = ManagementFactory.getGarbageCollectorMXBeans();

        baseInfo = baseInfo + "\n======垃圾收集信息=======";
        for (GarbageCollectorMXBean gcm : gcmList) {
            baseInfo += "\n垃圾收集器名称:" + gcm.getName();
            long collectionTime = gcm.getCollectionTime();
            long collectionCount = gcm.getCollectionCount();
            baseInfo += "\n垃圾收集次数:" + collectionCount + " 次,垃圾收集时间:" + collectionTime + "毫秒";
        }

        return baseInfo;
    }

    // 线程信息
    public static String getThreadInfo(String baseInfo) {
        ThreadMXBean tm = (ThreadMXBean) ManagementFactory.getThreadMXBean();

        baseInfo = baseInfo + "\n======线程信息=======";

        baseInfo += "\n线程数:" + tm.getThreadCount();
        baseInfo += "\n最大线程数:" + tm.getPeakThreadCount();
        baseInfo += "\n守护线程数:" + tm.getDaemonThreadCount();

        return baseInfo;
    }


}

执行程序,输出结果类似如下:

======操作系统内存信息=======
操作系统的版本:Windows 10
操作系统内存已使用:7350 MB
操作系统内存剩余:8917 MB
操作系统总内存:16267 MB
======JVM内存信息=======
JVM内存已用的空间为:9 MB
JVM内存的空闲空间为:52 MB
JVM总内总存空间为:61 MB
JVM总内存最大空间为:61 MB
======堆内存信息=======
初始堆大小:64MB
最大值:61MB
已使用:9MB
======垃圾收集信息=======
垃圾收集器名称:PS Scavenge
垃圾收集次数:2 次,垃圾收集时间:5毫秒
垃圾收集器名称:PS MarkSweep
垃圾收集次数:0 次,垃圾收集时间:0毫秒
======线程信息=======
线程数:5
最大线程数:5
守护线程数:4
31 2022-02-14 14:55:56

代码下载 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿20

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值