java容器无法使用jmap命令
jmap是java一个常用的辅助工具,它可以输出所有内存中对象,来检查内存泄漏等问题,然而在容器里使用jmap
命令时,会遇到以下错误:
/ # ps -ef
PID USER TIME COMMAND
1 root 1h30 java -jar /app-salary.jar --sahara.config.file=/sahara.yml
67 root 0:00 sh
84 root 0:00 ps -ef
/ # jmap -dump:format=b,file=heap.bin 1
1: Unable to get pid of LinuxThreads manager thread
查看当前使用的Dockerfile,可以看到使用的镜像是openjdk:8-jdk-alpine
,信息如下:
FROM openjdk:8-jdk-alpine
LABEL maintainer="Qiu Shuhui"
RUN set -xe \
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
&& apk update \
&& apk add --no-cache ca-certificates ttf-dejavu fontconfig tzdata \
&& cp -rf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
COPY corehr.jar sahara.yml /
VOLUME ["/apps/logs", "/apps/file"]
ENTRYPOINT ["java", "-jar", "/corehr.jar", "--sahara.config.file=/sahara.yml"]
参考网络的文章,发现这是一个通用的bug,其中的解决方案就是使用tini来接管java进程,在基础镜像中添加tini安装包:
FROM openjdk:8-jdk-alpine
LABEL maintainer="Qiu Shuhui<qiush01@haid.com.cn>"
RUN set -xe \
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
&& apk update \
&& apk add --no-cache ca-certificates ttf-dejavu fontconfig tzdata tini \
&& cp -rf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
Docker启动换成以下:
ENTRYPOINT [ "/sbin/tini", "--", "java", "-XX:+UseG1GC", "-jar", "/app-salary.jar", "--sahara.config.file=/sahara.yml" ]
使用tini命令接管java进程时,可以发现多衍生了一个进程,当前的JAVA PID为6。
/ # ps -ef
PID USER TIME COMMAND
1 root 0:00 /sbin/tini -- java -XX:+UseG1GC -jar /workflow.jar --sahara.config.file=/sahara.yml
6 root 0:57 java -XX:+UseG1GC -jar /workflow.jar --sahara.config.file=/sahara.yml
65 root 0:00 sh
70 root 0:00 ps -ef
再使用jmap命令,一切正常。