Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java使用的内存比堆大小(或Docker内存限制)多得多_Java_Linux_Docker_Memory_Jvm - Fatal编程技术网

Java使用的内存比堆大小(或Docker内存限制)多得多

Java使用的内存比堆大小(或Docker内存限制)多得多,java,linux,docker,memory,jvm,Java,Linux,Docker,Memory,Jvm,对于我的应用程序,Java进程使用的内存远远大于堆大小 运行容器的系统开始出现内存问题,因为容器占用的内存远远大于堆大小 堆大小设置为128 MB(-Xmx128m-Xms128m),而容器占用高达1GB的内存。正常情况下,需要500MB。如果docker容器的限制低于(例如mem_limit=mem_limit=400MB),则进程将被操作系统的内存不足杀手杀死 您能解释一下为什么Java进程使用的内存比堆多得多吗?如何正确调整Docker内存限制的大小?有没有办法减少Java进程的堆外内存占

对于我的应用程序,Java进程使用的内存远远大于堆大小

运行容器的系统开始出现内存问题,因为容器占用的内存远远大于堆大小

堆大小设置为128 MB(
-Xmx128m-Xms128m
),而容器占用高达1GB的内存。正常情况下,需要500MB。如果docker容器的限制低于(例如
mem_limit=mem_limit=400MB
),则进程将被操作系统的内存不足杀手杀死

您能解释一下为什么Java进程使用的内存比堆多得多吗?如何正确调整Docker内存限制的大小?有没有办法减少Java进程的堆外内存占用?


我使用来自的命令收集有关该问题的一些详细信息

从主机系统获取容器使用的内存

$ docker stats --no-stream 9afcb62a26c8
CONTAINER ID        NAME                                                                                        CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
9afcb62a26c8        xx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.0acbb46bb6fe3ae1b1c99aff3a6073bb7b7ecf85   0.93%               461MiB / 9.744GiB   4.62%               286MB / 7.92MB      157MB / 2.66GB      57
从容器内部,我获取进程使用的内存

$ ps -p 71 -o pcpu,rss,size,vsize
%CPU   RSS  SIZE    VSZ
11.2 486040 580860 3814600

该应用程序是一个web服务器,使用Jetty/Jersey/CDI捆绑在36 MB的fat far中

使用以下版本的OS和Java(在容器内)。Docker映像基于
openjdk:11 jre slim

$ java -version
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment (build 11+28-Debian-1)
OpenJDK 64-Bit Server VM (build 11+28-Debian-1, mixed mode, sharing)
$ uname -a
Linux service1 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 GNU/Linux

Java需要大量内存。JVM本身需要大量内存才能运行。堆是虚拟机中可用的内存,可供应用程序使用。因为JVM是一个包含所有可能的好东西的大包袱,所以仅仅加载它就需要大量内存

从Java9开始,您有一个名为的东西,它可能会减少启动java应用程序时使用的内存(以及启动时间)。jigsaw项目和一个新的模块系统不一定是为了减少必要的内存而创建的,但是如果这很重要,您可以尝试一下

您可以查看以下示例:。通过使用模块系统,它实现了21MB的CLI应用程序(嵌入了JRE)。JRE占用的内存超过200mb。当应用程序启动时,这应该转化为分配更少的内存(许多未使用的JRE类将不再被加载)

下面是另一个不错的教程:

如果你不想花时间在这上面,你可以简单地得到分配更多的内存。有时它是最好的。

:

为什么当我指定-Xmx=1g时,JVM占用的内存超过1gb 记忆

指定-Xmx=1g告诉JVM分配1gb堆。不是 告诉JVM将其整个内存使用限制为1gb。有 卡片表、代码缓存和各种其他堆外数据 结构。用于指定总内存使用率的参数为 -XX:MaxRAM。请注意,如果-XX:MaxRam=500m,您的堆大约为250mb

Java可以看到主机内存大小,并且不知道任何容器内存限制。它不会产生内存压力,所以GC也不需要释放已使用的内存。我希望
XX:MaxRAM
能帮助您减少内存占用。最终,您可以调整GC配置(
-XX:MinHeapFreeRatio
-XX:MaxHeapFreeRatio
,…)


内存度量有多种类型。Docker似乎在报告RSS内存大小,这可能与
jcmd
报告的“提交”内存不同(Docker的旧版本将RSS+缓存报告为内存使用情况)。 良好的讨论和链接:


(RSS)内存也可以被容器中的其他一些实用程序占用—shell、进程管理器。。。我们不知道容器中还运行着什么以及如何启动容器中的进程。

如何正确调整Docker内存限制的大小?
$ docker stats --no-stream 9afcb62a26c8
CONTAINER ID        NAME                                                                                        CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
9afcb62a26c8        xx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.0acbb46bb6fe3ae1b1c99aff3a6073bb7b7ecf85   0.93%               461MiB / 9.744GiB   4.62%               286MB / 7.92MB      157MB / 2.66GB      57
通过监视应用程序一段时间来检查它。若要限制容器的内存,请尝试对docker run命令使用-m、-memory bytes选项,或者在其他情况下使用等效的选项 像

docker run-d——命名我的容器——内存500m
无法回答其他问题

TL;博士 内存的详细使用情况由本机内存跟踪(NMT)详细信息(主要是代码元数据和垃圾收集器)提供。除此之外,Java编译器和优化器C1/C2会消耗摘要中未报告的内存

使用JVM标志可以减少内存占用(但会产生影响)

Docker容器的大小必须通过测试应用程序的预期负载来完成


每个组件的详细信息 可以在容器内禁用共享类空间,因为其他JVM进程不会共享这些类。可以使用以下标志。它将删除共享类空间(17MB)

垃圾回收器串行内存占用最小,但在垃圾回收处理过程中暂停时间较长(请参阅)。可以使用以下标志启用它。它最多可以节省使用的GC空间(48MB)

可以使用以下标志禁用C2编译器,以减少用于决定是否优化方法的分析数据

-XX:+TieredCompilation -XX:TieredStopAtLevel=1
代码空间减少了20MB。此外,JVM外部的内存减少了80MB(NMT空间和RSS空间之间的差异)优化编译器C2需要100MB。

可以使用以下标志禁用C1和C2编译器

-Xint
JVM之外的内存现在低于提交的总空间。代码空间减少了43MB。请注意,这对应用程序的性能有很大影响禁用C1和C2编译器会减少170 MB的内存使用。

使用(C2的替换)会使内存占用空间稍微小一些。它增加了20MB的代码内存空间,并从外部JVM内存减少了60MB

本文提供了不同内存空间的一些相关信息。 Oracle在中提供了一些详细信息。有关中和中编译级别的更多详细信息。一些细节
-XX:+UseSerialGC
-XX:+TieredCompilation -XX:TieredStopAtLevel=1
-Xint
Address           Kbytes    RSS    Dirty Mode  Mapping
...
00007f2b3e557000   39592   32956       0 r--s- some-file-17405-Index.db
00007f2b40c01000   39600   33092       0 r--s- some-file-17404-Index.db
                           ^^^^^               ^^^^^^^^^^^^^^^^^^^^^^^^
Total memory = Heap + Code Cache + Metaspace + Symbol tables +
               Other JVM structures + Thread stacks +
               Direct buffers + Mapped files +
               Native Libraries + Malloc overhead + ...