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
}
}
我是运行:
- 高山 openjdk-11
- 容器内存限制:2GB
- AWS EKS。
- JVM 环境:-Djava.net.preferIPv4Stack=true -XX:InitialRAMPercentage=70.0 -XX:MaxRAMPercentage=85.0 -Dfile.encoding=UTF8
我注意到“operationSystem.totalPhysicalMemorySizeMB”是 JVM 理解为可用的内存量。
参数“-XX:MaxRAMPercentage=85.0”按预期工作。 (以1,907为参考)
我知道非堆内存是堆外内存,那么我是否应该使用非堆+堆来计算我的应用程序的总使用量。
问题:
我的主要疑问是关于“freePhysicalMemorySizeMB”,即使提交的内存(堆+非堆)具有相同的值,这个值在容器之间也有很大差异。
我读到 java 可以使用本机库 (JNI),这也会消耗内存。
是否应该预留超出heap+NonHeap预估的内存?如果是,是否可以知道多少?垃圾收集器会清除这些其他使用的内存吗?
“非堆”与“堆外”是否相同?
注意:我的 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 堆之外的所有内容。
我一直在研究和阅读一些关于内存使用的问题,即使这里有很好的答案,我也想尝试理解我在分析中收集的一些值。
我在下面写了这段代码只是为了展示我在哪里收集数据。 注:此代码不编译,仅供理解。
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
}
}
我是运行:
- 高山 openjdk-11
- 容器内存限制:2GB
- AWS EKS。
- JVM 环境:-Djava.net.preferIPv4Stack=true -XX:InitialRAMPercentage=70.0 -XX:MaxRAMPercentage=85.0 -Dfile.encoding=UTF8
我注意到“operationSystem.totalPhysicalMemorySizeMB”是 JVM 理解为可用的内存量。
参数“-XX:MaxRAMPercentage=85.0”按预期工作。 (以1,907为参考)
我知道非堆内存是堆外内存,那么我是否应该使用非堆+堆来计算我的应用程序的总使用量。
问题: 我的主要疑问是关于“freePhysicalMemorySizeMB”,即使提交的内存(堆+非堆)具有相同的值,这个值在容器之间也有很大差异。
我读到 java 可以使用本机库 (JNI),这也会消耗内存。
是否应该预留超出heap+NonHeap预估的内存?如果是,是否可以知道多少?垃圾收集器会清除这些其他使用的内存吗?
“非堆”与“堆外”是否相同?
注意:我的 pod 只是 运行 java 应用程序(和 alpine 本身)
should I use nonHeap+heap to calculate the total usage by my application.
没有。 Java 进程使用的总物理内存包括 JVM 未计算在内的许多内容。
有关详细信息,请参阅
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?
应用程序可以
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 堆之外的所有内容。