【問題解決】Alpine鏡像中執行jstack、arthas等命令提示Unable to get pid of LinuxThreads manager thread

問題現象

最近在處理項目上問題發現之前同事構建的AlpineLinux的鏡像不能執行jstack等JDK命令,報錯如下。

Unable to get pid of LinuxThreads manager thread

問題原因

問題的根本原因有兩點:

  1. Alpine Linux 使用的不是標準gnu libc (glibc),而是musl libc
  2. apk包管理器安裝的OpenJDK是IceTea修補程式版本的,已經停止維護了

這兩個原因導致了一個神奇的現象:當Java進程PID=1時,通過OpenJDK8執行JDK命令調用底層時會提示Unable to get pid of LinuxThreads manager thread,這個錯誤資訊來源於Alpine倉庫中OpenJDK源碼中的一個失誤,沒處理musl libc仍去調用了glibc的底層介面導致的。

如下是亞馬遜工程師對此倉庫中底層OpenJDK8源碼做的patch修復。

//git.alpinelinux.org/aports/tree/community/openjdk8/icedtea-issue13032.patch

解決方法

解決方法有以下幾種:

方案1、添加 docker 啟動參數

啟動容器命令參考如下:

docker run -d --init 省略其他參數鏡像名等

方案2、鏡像安裝tini,由它管理進程

Dockerfile中使用如下方式

RUN apk --update --no-cache add tini 
#利用ENTRYPOINT一定會執行的特點,將它作為PID=1託管進程
ENTRYPOINT ["tini"]
CMD java $JAVA_OPTS -jar app.jar

方案3、用Shell腳本啟動Java進程

編寫腳本 docker-entrypoint.sh

# !/bin/bash
java $JAVA_OPTS -jar app.jar

Dockerfile中使用如下方式

CMD /docker-entrypoint.sh

方案4、用Shell解釋器啟動Java進程

Dockerfile中使用如下方式

CMD /bin/sh -c "java $JAVA_OPTS -jar app.jar"

方案5、推薦:換一種基於glibc的鏡像

如 debian、ubuntu、centos等基礎鏡像封裝

Tags: