使用Java获取当前JVM的实际RAM使用情况

5
在HTOP中,您可以查看RES值(resident size),该值显示了JVM进程实际占用的RAM数量。现在,我想通过< b>仅使用纯Java 来获取该值。如果您告诉我这是不可能的,那也没关系。让我解释一下我尝试过的所有尝试,其中一个应用程序在htop中显示了887M的RES值:
  1. 通过MemoryMXBean结合committed HeapMemory和non Heapmemory,结果为726M
  2. 将所有ManagementFactory.getMemoryPoolMXBeans()的已提交内存相加,结果为737M
  3. runtime.totalMemory()返回515M
还有其他任何想法吗?

没有纯Java函数可以给你这个。你可以通过一些假设来估计它,但是你缺少内存映射文件、线程堆栈、共享库和直接内存,这些都不包括在你提到的计算中。在我编写的程序中,如果你使用得当,内存映射文件可能会超过其他所有内容。 - Peter Lawrey
1
所以我基本上被迫使用类似 top 的外部工具或者使用 JNI 快捷方式? - ASA
虽然通常情况下你会有一个外部程序来监控你的使用情况,但你想基于这个数字在应用程序中采取什么行动呢?请注意:低数字可能是一件坏事,而高数字可能是一件好事。 - Peter Lawrey
你想用这个做什么?对于基于Java的监控工具来说,这将非常有用,但根据整个系统内存让你的应用程序做出反应并不明智。即使系统有256GB并且空闲90%,你的JVM可能仅限于128MB,因此它对你没有任何好处。 - ssube
我被分配创建一个记录Tomcat CPU使用率、每个线程CPU使用率和各种内存指标的日志应用程序(本质上是一个小型自制分析器)。除了RAM使用监控之外,一切都运作正常。遗憾的是,在我的工作场所,JNI不受欢迎,如果你的替代方案是读取外部应用程序的输出,你自然希望有一种“本地”的方式。 - ASA
显示剩余3条评论
2个回答

3
我已经写好了:

public class RuntimeUtil {
private static final long MEGABYTE_FACTOR = 1024L * 1024L;
private static final DecimalFormat ROUNDED_DOUBLE_DECIMALFORMAT;
private static final String MIB = "MiB";

static {
    DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(Locale.ENGLISH);
    otherSymbols.setDecimalSeparator('.');
    otherSymbols.setGroupingSeparator(',');
    ROUNDED_DOUBLE_DECIMALFORMAT = new DecimalFormat("####0.00", otherSymbols);
    ROUNDED_DOUBLE_DECIMALFORMAT.setGroupingUsed(false);
}

private RuntimeUtil() {
    //No Init
}

public static long getMaxMemory() {
    return Runtime.getRuntime().maxMemory();
}

public static long getUsedMemory() {
    return getMaxMemory() - getFreeMemory();
}

public static long getTotalMemory() {
    return Runtime.getRuntime().totalMemory();
}

public static long getFreeMemory() {
    return Runtime.getRuntime().freeMemory();
}

public static String getTotalMemoryInMiB() {
    double totalMiB = bytesToMiB(getTotalMemory());
    return String.format("%s %s", ROUNDED_DOUBLE_DECIMALFORMAT.format(totalMiB), MIB);
}

public static String getFreeMemoryInMiB() {
    double freeMiB = bytesToMiB(getFreeMemory());
    return String.format("%s %s", ROUNDED_DOUBLE_DECIMALFORMAT.format(freeMiB), MIB);
}

public static String getUsedMemoryInMiB() {
    double usedMiB = bytesToMiB(getUsedMemory());
    return String.format("%s %s", ROUNDED_DOUBLE_DECIMALFORMAT.format(usedMiB), MIB);
}

public static String getMaxMemoryInMiB() {
    double maxMiB = bytesToMiB(getMaxMemory());
    return String.format("%s %s", ROUNDED_DOUBLE_DECIMALFORMAT.format(maxMiB), MIB);
}

public static double getPercentageUsed() {
    return ((double) getUsedMemory() / getMaxMemory()) * 100;
}

public static String getPercentageUsedFormatted() {
    double usedPercentage = getPercentageUsed();
    return ROUNDED_DOUBLE_DECIMALFORMAT.format(usedPercentage) + "%";
}

private static double bytesToMiB(long bytes) {
    return ((double) bytes / MEGABYTE_FACTOR);
}

public static String getHostAdress() {
    try {
        java.net.InetAddress addr = java.net.InetAddress.getLocalHost();
        return addr.getHostAddress();
    } catch (UnknownHostException e) {
        // looks like a strange machine
        System.out.println(e.getMessage());
    }
    return StringUtil.EMPTY;
}

public static String getHostName() {
    try {
        java.net.InetAddress addr = java.net.InetAddress.getLocalHost();
        return addr.getHostName();
    } catch (UnknownHostException e) {
        // looks like a strange machine
        System.out.println(e.getMessage());
    }
    return StringUtil.EMPTY;
}

public static String getSystemInformation() {
    return String.format("SystemInfo=Current heap:%s; Used:%s; Free:%s; Maximum Heap:%s; Percentage Used:%s",
            getTotalMemoryInMiB(),
            getUsedMemoryInMiB(),
            getFreeMemoryInMiB(),
            getMaxMemoryInMiB(),
            getPercentageUsedFormatted());
}

3
假设您正在运行Linux,则只需读取/proc/self/status文件并查找VmRSS:行即可。
或者解析/proc/self/smaps以获取当前进程的全面内存信息。

我不相信这是纯Java(它依赖于系统函数并在Windows下崩溃),尽管这是一个有用的答案。 - Pokechu22
这可能是最干净、最标准的方法。如果要填写Windows支持,您可以考虑使用WMI COM接口(在此讨论)。 - ssube

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接