与堆使用相比,Java应用程序的巨大系统内存使用量

时间:2016-07-06 12:18:13

标签: java memory memory-leaks garbage-collection jvm

我有像java框架这样的微服务。许多java进程在一个盒子上运行(ubuntu 14.04.4 LTS)。 java进程使用很多系统内存,因此交换空间被大量使用。 jstat gc报告不解释系统内存使用情况。所有java进程都使用参数

运行
-XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90

强制JVM将内存返回给系统。没有参数,问题仍然存在。一些java组件使用nashorn引擎来编写某些功能。

有人可以解释这里的行为吗?

是否存在限制系统内存使用量的jvm patameters?

如何命令操作系统对jvm的内存分配更具限制性?

一些数据:

组件A(使用nashorn)

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
2400 xxxxxx    20   0 13.933g 807496   7332 S   0.0  2.5   4180:15 java

jstat -gc 2400:

S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
512.0  512.0   0.0   400.0  19456.0  12751.6   62464.0    59862.3   89688.0 84866.6 10624.0 9440.4 2165265 15977.896 16816 1813.836 17791.732
  • 容量:ca。 180 MB
  • 用法:ca。 165 MB
  • 系统资源:ca。 800 MB

为什么组件使用GC区域内存的4倍?

组件B(没有nashorn)

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
19476  xxxx     20   0 13.465g 120436   7836 S   7.0  0.4  22:40.76 java

jstat -gc 19476:

S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
512.0  512.0   0.0    0.0   41472.0  25408.7   343040.0    7164.5   17664.0 17183.1 2048.0 1919.4   3650   10.806  939    16.788   27.594
  • 容量:ca。 403 MB
  • 用法:ca。 52 MB
  • 系统资源:120 MB

此处GC区域容量大于实际系统内存使用量。系统内存使用量仍然是GC区域的两倍。 IMO这个组件表现正常,因为库等也部分映射到内存中。

组件C(没有nashorn)

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
2272 xxxxxx    20   0 13.382g 922944  11108 S   0.7  2.8  40033:41 java

jstat -gc 2272:

S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
1024.0 1024.0 868.0   0.0   36352.0  23866.1   76800.0    56580.2   68864.0 64571.1 8448.0 7460.6 31974159 199295.501 844692 134644.040 333939.541
  • 容量:ca。 190 MB
  • 用法:ca。 152 MB
  • 系统资源:920 MB

为什么组件使用GC区域内存的6倍?

1 个答案:

答案 0 :(得分:2)

  

有人可以解释这里的行为吗?

内存使用没有单一的解释,有很多因素。

  • 使用NMT概述JVM的各个内部部分分配了多少内存
  • 使用pmap -x <pid>识别内存映射文件。
  • 获取堆转储以查找直接内存缓冲区(它们只显示为pmap中的某些[anon]映射)或使用Yourkit进行内存检查以识别直接分配的数量缓冲区。在运行时,您可以使用BufferPoolMXBean跟踪直接缓冲区的使用情况。

除此之外,你必须考虑到每个JVM都带有一些基线内存消耗,并且需要为垃圾收集器提供喘息空间。在共享JVM中运行多个服务可以分摊这些基准成本。

由于虚拟内存系统的复杂性,您还需要了解difference between used, committed, reserved and resident memory

  

是否存在限制系统内存使用量的jvm patameters?

这取决于原因。

对于托管堆,它可以make it yield unused memory back to the OS more swiftly,但会带来性能损失。