Java 容器内堆外内存

Java memory off heap inside container

我一直在研究和阅读一些关于内存使用的问题,即使这里有很好的答案,我也想尝试理解我在分析中收集的一些值。

我在下面写了这段代码只是为了展示我在哪里收集数据。 注:此代码不编译,仅供理解。

       long KB_FACTOR = 1024;
        long MB_FACTOR = 1024 * KB_FACTOR;

        OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
        "operationSystem.totalPhysicalMemorySizeMB" = os.getTotalPhysicalMemorySize() / MB_FACTOR);
        "operationSystem.freePhysicalMemorySizeMB"  = os.getFreePhysicalMemorySize() / MB_FACTOR);

        long freeMemoryBytes = Runtime.getRuntime().freeMemory();
        long totalMemoryBytes = Runtime.getRuntime().totalMemory();
        long maxMemoryBytes = Runtime.getRuntime().maxMemory();
        "memory.maxMB" = (maxMemoryBytes / MB_FACTOR);
        "memory.freeMB" = (freeMemoryBytes / MB_FACTOR);
        "memory.totalMB" = (totalMemoryBytes / MB_FACTOR);

        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
        "memoryHeap.commitedMB" = (heapMemoryUsage.getCommitted() / MB_FACTOR);
        "memoryHeap.maxMB" = (heapMemoryUsage.getMax() / MB_FACTOR);

        MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
       "memoryNonHeap.commitedMB" =  (nonHeapMemoryUsage.getCommitted() / MB_FACTOR);
       "memoryNonHeap.maxMB" = (nonHeapMemoryUsage.getMax() / MB_FACTOR);

       "memoryHeap+NonHeap.committedMB" = (heapMemoryUsage.getCommitted() / MB_FACTOR) + (nonHeapMemoryUsage.getCommitted() / MB_FACTOR);

这是我收集的一些数据: 容器 01

 {
        "memory": {
            "freeMB": 611,
            "maxMB": 1622,
            "totalMB": 1336
        },
        "memoryHeap": {
            "committedMB": 1336,
            "maxMB": 1622
        },
        "memoryNonHeap": {
            "initMB": 7,
            "usedMB": 219,
            "committedMB": 227,
            "maxMB": 0
        },
        "memoryHeap+NonHeap": {
            "committedMB": 1563
        },
        "operationSystem": {
            "totalPhysicalMemorySizeMB": 1907,
            "freePhysicalMemorySizeMB": 390
        }
    }

容器 02:

{
    "memory": {
        "freeMB": 303,
        "maxMB": 1622,
        "totalMB": 1336
    },
    "memoryHeap": {
        "committedMB": 1336,
        "maxMB": 1622
    },
    "memoryNonHeap": {
        "committedMB": 244,
        "maxMB": 0
    },
    "memoryHeap+NonHeap": {
        "committedMB": 1580
    },
    "operationSystem": {
        "totalPhysicalMemorySizeMB": 1907,
        "freePhysicalMemorySizeMB": 87
    }
}

我是运行:

我注意到“operationSystem.totalPhysicalMemorySizeMB”是 JVM 理解为可用的内存量。

参数“-XX:MaxRAMPercentage=85.0”按预期工作。 (以1,907为参考)

我知道非堆内存是堆外内存,那么我是否应该使用非堆+堆来计算我的应用程序的总使用量。

问题: 我的主要疑问是关于“freePhysicalMemorySizeMB”,即使提交的内存(堆+非堆)具有相同的值,这个值在容器之间也有很大差异。

我读到 java 可以使用本机库 (JNI),这也会消耗内存。

注意:我的 pod 只是 运行 java 应用程序(和 alpine 本身)

should I use nonHeap+heap to calculate the total usage by my application.

没有。 Java 进程使用的总物理内存包括 JVM 未计算在内的许多内容。
有关详细信息,请参阅 and this presentation

My main doubt is about "freePhysicalMemorySizeMB", this value variates a lot between containers even when the committed memories (heap+nonHeap) have the same value .

就是别看getFreePhysicalMemorySize()。这个值很少有用。它没有考虑 page cache 和各种可回收的 OS 结构,这些结构可以在应用程序请求更多内存时自动释放。

进程内存使用量最有意义的度量是RSS - the resident size. An easy way to find the application's own RSS on Linux is to read /proc/self/stat

Should I reserve more memory beyond the estimate of heap+NonHeap? If yes, is it possible to know how much?

应用程序可以 than Heap+NonHeap. It's not easy to guess the right number statically, so your best bet is to watch the actual RSS 并相应地调整限制。

Is it the term "NonHeap" the same as "off-heap"?

视情况而定。例如,在jconsole和其他一些工具中,Non-Heap表示certain JVM structures:Metaspace,Compress Class Space,Code Cache。 Off-heap 通常是一个更广泛的术语,它基本上意味着除 Java 堆之外的所有内容。