JavaでJVM情報を取得する方法

JVM情報の取得にはManagementFactoryを使用し、OSの実行情報にはOSHIライブラリを推奨します。

<dependency>
   <groupId>com.github.oshi</groupId>
   <artifactId>oshi-core</artifactId>
   <version>5.7.5</version>
</dependency>

メモリサイズのフォーマット用クラス

package com.example.utils;

import java.text.DecimalFormat;

/**
 * メモリサイズをフォーマットするユーティリティクラス
 */
public class MemoryFormatter {

    /**
     * バイト数を適切な単位に変換
     *
     * @param bytes バイト数
     * @return フォーマットされた文字列
     */
    public static String formatMemorySize(long bytes) {
        // 基準となる変換値
        double BASE = 1024.0;
        double kb = bytes / BASE;
        
        if (kb < BASE) {
            return new DecimalFormat("#.##KB").format(kb);
        }
        
        double mb = kb / BASE;
        if (mb < BASE) {
            return new DecimalFormat("#.##MB").format(mb);
        }
        
        double gb = mb / BASE;
        if (gb < BASE) {
            return new DecimalFormat("#.##GB").format(gb);
        }
        
        double tb = gb / BASE;
        return new DecimalFormat("#.##TB").format(tb);
    }
}

ManagementFactoryを使用してMemoryMXBeanを取得

MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
 
 // ヒープメモリ情報
System.out.println("最大容量:" + MemoryFormatter.formatMemorySize(memoryBean.getHeapMemoryUsage().getMax()));    
System.out.println("初期容量:" + MemoryFormatter.formatMemorySize(memoryBean.getHeapMemoryUsage().getInit()));  
System.out.println("確保済み容量:" + MemoryFormatter.formatMemorySize(memoryBean.getHeapMemoryUsage().getCommitted()));   
System.out.println("使用済み容量:" + MemoryFormatter.formatMemorySize(memoryBean.getHeapMemoryUsage().getUsed()));  
System.out.println(memoryBean.getHeapMemoryUsage().toString());   
        
// ヒープ外メモリ情報
System.out.println("最大容量:" + MemoryFormatter.formatMemorySize(memoryBean.getNonHeapMemoryUsage().getMax()));    
System.out.println("初期容量:" + MemoryFormatter.formatMemorySize(memoryBean.getNonHeapMemoryUsage().getInit()));  
System.out.println("確保済み容量:" + MemoryFormatter.formatMemorySize(memoryBean.getNonHeapMemoryUsage().getCommitted()));   
System.out.println("使用済み容量:" + MemoryFormatter.formatMemorySize(memoryBean.getNonHeapMemoryUsage().getUsed()));  
System.out.println(memoryBean.getNonHeapMemoryUsage().toString()); 

Runtimeオブジェクトを使用した情報取得

JsonObject systemInfo = new JsonObject();
Properties props = System.getProperties();
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();

// JVM総メモリ容量
systemInfo.addProperty("totalMemory", MemoryFormatter.formatMemorySize(totalMemory));

// 空きメモリ容量
systemInfo.addProperty("freeMemory", MemoryFormatter.formatMemorySize(freeMemory));

// JVM最大申請可能容量
systemInfo.addProperty("maxMemory", MemoryFormatter.formatMemorySize(runtime.maxMemory()));

// JVM使用済みメモリ容量
systemInfo.addProperty("usedMemory", MemoryFormatter.formatMemorySize(totalMemory - freeMemory));

// JVMメモリ使用率
systemInfo.addProperty("memoryUsageRate", new DecimalFormat("#.##%").format((totalMemory - freeMemory) * 1.0 / totalMemory));

// JDKバージョン
systemInfo.addProperty("jdkVersion", props.getProperty("java.version"));

// JDKインストールパス
systemInfo.addProperty("jdkHome", props.getProperty("java.home"));
        
System.out.println(systemInfo.toString());

JVMスレッド情報の取得

ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
Map<String, Number> threadStats = new LinkedHashMap<String, Number>();
// スレッド総数
threadStats.put("totalThreadCount", threadBean.getThreadCount());
// デーモンスレッド数
threadStats.put("daemonThreadCount", threadBean.getDaemonThreadCount());
// 開始されたスレッド総数
threadStats.put("totalStartedThreadCount", threadBean.getTotalStartedThreadCount());
// スレッド詳細情報の取得
ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadBean.getAllThreadIds())

int newThreadCount = 0;
int runnableCount = 0;
int blockedCount = 0;
int waitingCount = 0;
int timedWaitingCount = 0;
int terminatedCount = 0;
if (threadInfos != null) {
   for (ThreadInfo threadInfo : threadInfos) {
                if (threadInfo != null) {
                    switch (threadInfo.getThreadState()) {
                        case NEW:
                            newThreadCount++;
                            break;
                        case RUNNABLE:
                            runnableCount++;
                            break;
                        case BLOCKED:
                            blockedCount++;
                            break;
                        case WAITING:
                            waitingCount++;
                            break;
                        case TIMED_WAITING:
                            timedWaitingCount++;
                            break;
                        case TERMINATED:
                            terminatedCount++;
                            break;
                        default:
                            break;
                    }
                } else {
                    terminatedCount++;
                }
            }
// 新規スレッド数            
threadStats.put("newThreadCount", newThreadCount);
// 実行中スレッド数   
threadStats.put("runnableThreadCount", runnableCount);
// ブロック中スレッド数   
threadStats.put("blockedThreadCount", blockedCount);
// 待機中スレッド数   
threadStats.put("waitingThreadCount", waitingCount);
// タイムアウト待機中スレッド数   
threadStats.put("timedWaitingThreadCount", timedWaitingCount);
// 終了スレッド数   
threadStats.put("terminatedThreadCount", terminatedCount);

long[] deadlockedIds = threadBean.findDeadlockedThreads();
threadStats.put("deadlockedThreadCount", deadlockedIds == null ? 0 : deadlockedIds.length);

システムCPU情報の取得

JsonObject cpuStats = new JsonObject();
CentralProcessor processor = hardware.getProcessor();
        // CPU情報取得
long[] prevTicks = processor.getSystemCpuLoadTicks();
Util.sleep(OSHI_WAIT_SECOND);
long[] ticks = processor.getSystemCpuLoadTicks();
long niceValue = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
long irqValue = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
long softirqValue = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
long stealValue = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
long systemValue = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
long userValue = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
long iowaitValue = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
long idleValue = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
long totalCpu = userValue + niceValue + systemValue + idleValue + iowaitValue + irqValue + softirqValue + stealValue;
        // CPUコア数
cpuStats.addProperty("cpuCoreCount", processor.getLogicalProcessorCount());
        // システム使用率
cpuStats.addProperty("systemUsageRate", new DecimalFormat("#.##%").format(systemValue * 1.0 / totalCpu));
        // ユーザー使用率
cpuStats.addProperty("userUsageRate", new DecimalFormat("#.##%").format(userValue * 1.0 / totalCpu));
        // I/O待機率
cpuStats.addProperty("iowaitRate", new DecimalFormat("#.##%").format(iowaitValue * 1.0 / totalCpu));
        // 全体使用率
cpuStats.addProperty("totalUsageRate", new DecimalFormat("#.##%").format(1.0 - (idleValue * 1.0 / totalCpu)));
 System.out.println(cpuStats.toString());

システムメモリ情報の取得(JVM外)

package com.example.system;

import lombok.extern.slf4j.Slf4j;
import oshi.SystemInfo;
import oshi.hardware.*;
import oshi.software.os.FileSystem;
import oshi.software.os.NetworkParams;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.FormatUtil;

import java.util.Arrays;
import java.util.List;

/**
 * システム情報収集クラス
 */
@Slf4j
public class SystemInfoCollector {
    public static void main(String[] args) {
        log.info("システム情報の初期化開始...");
        SystemInfo sysInfo = new SystemInfo();

        HardwareAbstractionLayer hal = sysInfo.getHardware();
        OperatingSystem os = sysInfo.getOperatingSystem();

        log.info("コンピュータシステム情報の取得...");
        printComputerSystem(hal.getComputerSystem());

        log.info("プロセッサ情報の取得...");
        printProcessor(hal.getProcessor());

        log.info("メモリ情報の取得...");
        printMemory(hal.getMemory());

        log.info("CPU情報の取得...");
        printCpu(hal.getProcessor());

        log.info("センサー情報の取得...");
        printSensors(hal.getSensors());

        log.info("電源情報の取得...");
        printPowerSources(hal.getPowerSources());

        log.info("ディスク情報の取得...");
        printDisks(hal.getDiskStores());

        log.info("ファイルシステム情報の取得...");
        printFileSystem(os.getFileSystem());

        log.info("ネットワークインターフェース情報の取得...");
        printNetworkInterfaces(hal.getNetworkIFs());

        log.info("ネットワークパラメータ情報の取得...");
        printNetworkParameters(os.getNetworkParams());

        // ハードウェア: ディスプレイ情報
        log.info("ディスプレイ情報の取得...");
        printDisplays(hal.getDisplays());

        // ハードウェア: USBデバイス情報
        log.info("USBデバイス情報の取得...");
        printUsbDevices(hal.getUsbDevices(true));
    }

    private static void printComputerSystem(final ComputerSystem computerSystem) {
        System.out.println("メーカー: " + computerSystem.getManufacturer());
        System.out.println("モデル: " + computerSystem.getModel());
        System.out.println("シリアル番号: " + computerSystem.getSerialNumber());
        
        final Firmware firmware = computerSystem.getFirmware();
        System.out.println("ファームウェア:");
        System.out.println("  メーカー: " + firmware.getManufacturer());
        System.out.println("  名称: " + firmware.getName());
        System.out.println("  説明: " + firmware.getDescription());
        System.out.println("  バージョン: " + firmware.getVersion());
        
        final Baseboard baseboard = computerSystem.getBaseboard();
        System.out.println("ベースボード:");
        System.out.println("  メーカー: " + baseboard.getManufacturer());
        System.out.println("  モデル: " + baseboard.getModel());
        System.out.println("  バージョン: " + baseboard.getVersion());
        System.out.println("  シリアル番号: " + baseboard.getSerialNumber());
    }

    private static void printProcessor(CentralProcessor processor) {
        System.out.println(processor);
        System.out.println(" 物理CPUパッケージ数: " + processor.getPhysicalPackageCount());
        System.out.println(" 物理CPUコア数: " + processor.getPhysicalProcessorCount());

        System.out.println("識別子: " + processor.getProcessorIdentifier());
        System.out.println("プロセッサID: " + processor.getProcessorIdentifier());
    }

    private static void printMemory(GlobalMemory memory) {
        System.out.println("メモリ: " + FormatUtil.formatBytes(memory.getAvailable()) + "/"
                + FormatUtil.formatBytes(memory.getTotal()));
        System.out.println("スワップ使用量: " + FormatUtil.formatBytes(memory.getVirtualMemory().getSwapUsed()) + "/"
                + FormatUtil.formatBytes(memory.getVirtualMemory().getSwapTotal()));
    }

    private static void printCpu(CentralProcessor processor) {
        System.out.println(
                "コンテキストスイッチ/割り込み回数: " + processor.getContextSwitches() + " / " + processor.getInterrupts());

        long[] prevTicks = processor.getSystemCpuLoadTicks();
        System.out.println("0秒時点のCPU、IOWait、IRQティック: " + Arrays.toString(prevTicks));
        
        // 1秒待機
        long[] ticks = processor.getSystemCpuLoadTicks();
        System.out.println("1秒時点のCPU、IOWait、IRQティック: " + Arrays.toString(ticks));
        
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal;

        System.out.format(
                "ユーザー: %.1f%% ナイス: %.1f%% システム: %.1f%% アイドル: %.1f%% I/O待機: %.1f%% 割り込み: %.1f%% ソフト割り込み: %.1f%% スティール: %.1f%%%n",
                100d * user / totalCpu, 100d * nice / totalCpu, 100d * sys / totalCpu, 100d * idle / totalCpu,
                100d * iowait / totalCpu, 100d * irq / totalCpu, 100d * softirq / totalCpu, 100d * steal / totalCpu);
        
        double[] loadAverage = processor.getSystemLoadAverage(3);
        System.out.println("CPU負荷平均:" + (loadAverage[0] < 0 ? " N/A" : String.format(" %.2f", loadAverage[0]))
                + (loadAverage[1] < 0 ? " N/A" : String.format(" %.2f", loadAverage[1]))
                + (loadAverage[2] < 0 ? " N/A" : String.format(" %.2f", loadAverage[2])));
    }

    private static void printSensors(Sensors sensors) {
        System.out.println("センサー情報:");
        System.out.format(" CPU温度: %.1f°C%n", sensors.getCpuTemperature());
        System.out.println(" ファン速度: " + Arrays.toString(sensors.getFanSpeeds()));
        System.out.format(" CPU電圧: %.1fV%n", sensors.getCpuVoltage());
    }

    private static void printPowerSources(List<PowerSource> powerSources) {
        StringBuilder sb = new StringBuilder("電源情報: ");
        if (powerSources.size() == 0) {
            sb.append("不明");
        } else {
            double remainingTime = powerSources.get(0).getTimeRemainingInstant();
            if (remainingTime < -1d) {
                sb.append("充電中");
            } else if (remainingTime < 0d) {
                sb.append("残り時間計算中");
            } else {
                sb.append(String.format("%d:%02d 残り", (int) (remainingTime / 3600),
                        (int) (remainingTime / 60) % 60));
            }
        }
        for (PowerSource pSource : powerSources) {
            sb.append(String.format("%n %s @ %.1f%%", pSource.getName(), pSource.getTimeRemainingInstant() * 100d));
        }
        System.out.println(sb.toString());
    }

    private static void printDisks(List<HWDiskStore> diskStores) {
        System.out.println("ディスク情報:");
        for (HWDiskStore disk : diskStores) {
            boolean hasActivity = disk.getReads() > 0 || disk.getWrites() > 0;
            System.out.format(" %s: (モデル: %s - S/N: %s) サイズ: %s, 読み取り: %s (%s), 書き込み: %s (%s), 転送時間: %s ms%n",
                    disk.getName(), disk.getModel(), disk.getSerial(),
                    disk.getSize() > 0 ? FormatUtil.formatBytesDecimal(disk.getSize()) : "?",
                    hasActivity ? disk.getReads() : "?", hasActivity ? FormatUtil.formatBytes(disk.getReadBytes()) : "?",
                    hasActivity ? disk.getWrites() : "?", hasActivity ? FormatUtil.formatBytes(disk.getWriteBytes()) : "?",
                    hasActivity ? disk.getTransferTime() : "?");
            
            List<HWPartition> partitions = disk.getPartitions();
            if (partitions == null) {
                continue;
            }
            for (HWPartition part : partitions) {
                System.out.format(" |-- %s: %s (%s) メジャー:マイナー=%d:%d, サイズ: %s%s%n", 
                        part.getIdentification(),
                        part.getName(), part.getType(), part.getMajor(), part.getMinor(),
                        FormatUtil.formatBytesDecimal(part.getSize()),
                        part.getMountPoint().isEmpty() ? "" : " @ " + part.getMountPoint());
            }
        }
    }

    private static void printFileSystem(FileSystem fileSystem) {
        System.out.println("ファイルシステム情報:");

        System.out.format(" ファイルディスクリプタ: %d/%d%n", fileSystem.getOpenFileDescriptors(),
                fileSystem.getMaxFileDescriptors());

        List<OSFileStore> fsList = fileSystem.getFileStores();
        for (OSFileStore fs : fsList) {
            long usable = fs.getUsableSpace();
            long total = fs.getTotalSpace();
            System.out.format(
                    " %s (%s) [%s] %s of %s 空き (%.1f%%) %s "
                            + (fs.getLogicalVolume() != null && fs.getLogicalVolume().length() > 0 ? "[%s]" : "%s")
                            + " マウントポイント: %s%n",
                    fs.getName(), fs.getDescription().isEmpty() ? "ファイルシステム" : fs.getDescription(), fs.getType(),
                    FormatUtil.formatBytes(usable), FormatUtil.formatBytes(fs.getTotalSpace()), 100d * usable / total,
                    fs.getVolume(), fs.getLogicalVolume(), fs.getMount());
        }
    }

    private static void printNetworkInterfaces(List<NetworkIF> networkIFs) {
        System.out.println("ネットワークインターフェース情報:");
        for (NetworkIF net : networkIFs) {
            System.out.format(" 名前: %s (%s)%n", net.getName(), net.getDisplayName());
            System.out.format("   MACアドレス: %s %n", net.getMacaddr());
            System.out.format("   MTU: %s, 速度: %s %n", net.getMTU(), FormatUtil.formatValue(net.getSpeed(), "bps"));
            System.out.format("   IPv4: %s %n", Arrays.toString(net.getIPv4addr()));
            System.out.format("   IPv6: %s %n", Arrays.toString(net.getIPv6addr()));
            boolean hasData = net.getBytesRecv() > 0 || net.getBytesSent() > 0 || net.getPacketsRecv() > 0
                    || net.getPacketsSent() > 0;
            System.out.format("   トラフィック: 受信 %s/%s%s; 送信 %s/%s%s %n",
                    hasData ? net.getPacketsRecv() + " パケット" : "?",
                    hasData ? FormatUtil.formatBytes(net.getBytesRecv()) : "?",
                    hasData ? " (" + net.getInErrors() + " エラー)" : "",
                    hasData ? net.getPacketsSent() + " パケット" : "?",
                    hasData ? FormatUtil.formatBytes(net.getBytesSent()) : "?",
                    hasData ? " (" + net.getOutErrors() + " エラー)" : "");
        }
    }

    private static void printNetworkParameters(NetworkParams networkParams) {
        System.out.println("ネットワークパラメータ情報:");
        System.out.format(" ホスト名: %s%n", networkParams.getHostName());
        System.out.format(" ドメイン名: %s%n", networkParams.getDomainName());
        System.out.format(" DNSサーバー: %s%n", Arrays.toString(networkParams.getDnsServers()));
        System.out.format(" IPv4ゲートウェイ: %s%n", networkParams.getIpv4DefaultGateway());
        System.out.format(" IPv6ゲートウェイ: %s%n", networkParams.getIpv6DefaultGateway());
    }

    private static void printDisplays(List<Display> displays) {
        System.out.println("ディスプレイ情報:");
        int i = 0;
        for (Display display : displays) {
            System.out.println(" ディスプレイ " + i + ":");
            System.out.println(display.toString());
            i++;
        }
    }

    private static void printUsbDevices(List<UsbDevice> usbDevices) {
        System.out.println("USBデバイス情報:");
        for (UsbDevice usbDevice : usbDevices) {
            System.out.println(usbDevice.toString());
        }
    }
}

タグ: Java JVM OSHI ManagementFactory

8月23日 10:25 投稿