这篇文章主要介绍了docker如何查看jvm内存占用方式,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
一、进入docker容器的宿主机,查看运行指定镜像的容器id(结果的第一列):
docker ps | grep myImageName(或docker ps | grep java)
二、进入容器内部:
docker exec -it containerId sh
三、直接输入top命令:
top
可看到基本的容器占用的信息:pid、vsz、cpu、command等。(ctrl+c 或 q,退出top)
四、查看更具体的jvm内存占用:
top -m
其中,vsz:Virtual Memory Size,虚拟内存大小,表明了该进程可以访问的所有内存,包括被交换的内存和共享库内存。
rss: Resident Set Size,常驻内存集合大小,表示进程在RAM中占用了多少内存,并不包含在SWAP中占用的虚拟内存。即使是在内存中的使用了共享库的内存大小也一并计算在内,包含了完整的在stack和heap中的内存。
SHR:shared memory,共享内存。
补充:
ps -ef | grep java 或 docker top 容器id ,可查看pid的一些信息。
ps aux | grep java。
top -p pid。
RSS
是常驻内存集(Resident Set Size),表示该进程分配的内存大小。
RSS
不包括进入交换分区的内存。
RSS
包括共享库占用的内存(只要共享库在内存中)
RSS
包括所有分配的栈内存和堆内存。
VSZ
表示进程分配的虚拟内存。
VSZ
包括进程可以访问的所有内存,包括进入交换分区的内容,以及共享库占用的内存。
VSZRW:未百度到具体含义,猜测:初始申请的虚拟内存大小。
docker stats 容器名 或 docker stats 容器id,结果如下:
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
补充:docker容器化下的JVM参数调优
1、JVM堆内存设置
跑在docker容器的Java服务发生过几次内存超标异常,实际上这和Java程序的docker容器化有很大的关系。Java和docker并不是天然的朋友,docker可以设置内存和CPU限制,底层通过Linux cgroup技术实现,但是Java JVM并不能自动检测到。
我们可以使用Java的Xmx标识手动指定堆内存的大小或者使用较高版本的JDK提供的JVM标识,解决这个问题。
问题:
旧版本Java8(update 131之前的版本),JVM的可用内存和CPU数量并不是docker允许你使用的可用内存和CPU数量
比如docker容器中限制只能使用1G,但是旧版本Java并不能识别到这个限制,当业务增长时,JVM就会申请更多内存,可能远超这个限制。但是如果使用太多内存,docker就会采取行动并杀死容器内的Java进程,显然这不是我们想要的!
目前我们生产环境使用Java8版本,这个问题可通过-Xmx限制堆内存大小来解决,不过这里实际限制了两次,一次是docker容器的内存限制,一次是jvm堆内存的限制。
解决方法:
这个前提需要Java程序的dockerfile支持:
# 初始镜像 得到adoptopenjdk/openjdk8 #,jar包名字需要更改为项目名字——版本号,后面app.jar 不变 ADD example-sun-1.0.jar  app.jar #,配置JVM启动参数 ENV JVM_ARGS=$ {JVM_ARGS} EXPOSE 8080 #,优化jvm参数配置启动 ENTRYPOINT java $ {JVM_ARGS}, -Djava.security.egd=文件:/dev/?urandom -jar 应用。jar
具体在k8部署。yaml部署文件中环境变量env中加入以下参数,当JVM启动时就会加载进去
安康;名称:JVM_ARGS ,价值:-Xmx1024m -Xms512m
Xmx1024m #设置jvm堆内存的最大值
-Xms512m #设置jvm堆内存的最小值
这里设置最小堆内存为512米,最大内存为1024米,堆内存调整不要一味简单增大,要仔细分析内存占用过大的原因,是否有代码上的问题。