歡迎您光臨本站 註冊首頁

Java長期運行后, jps等工具無法連接jvm

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

  相信很多朋友都遇見過, 一個Java應用長期運行后, 發現jps, jstack, jstat等工具都無法連接正在運行的jvm了. 如果這個時候發生故障, 非常難以診斷. 一直以來, 我都以為是Java的bug.

  最近偶然得知, jps的工作模式是讀取了系統臨時文件夾下的pid文件里的內容獲得連接信息的. 這個文件夾在Linux下的名字是:/tmp/hsperfdata_$USER ($USER是啟動Java程序的用戶). 我們都知道系統臨時文件夾可能會被某些臨時文件夾工具自動刪除, 比如:

  1. tmpwatch: redhat linux發行版使用的刪除工具

  2. tmpreaper: ubuntu linux 發行版使用的刪除工具

  這些工具可能是沒有安裝的. 那麼就不會發生刪除/tmp/hsperfdata_$USER的事情.

  我們觀察到, redhat5.2/5.3 的刪除工具的存在一些瑕疵, tmpwatch -umc 會按照最長時間來確定刪除.看看umc參數定義:

  Java代碼

  -----------------------------------

  If the --atime, --ctime or --mtime options are used in combination, the decision about deleting a file will be based on the maximum of these times.

  -----------------------------------

  -u, --atime

  Make the decision about deleting a file based on the file's atime (access time). This is the default.

  Note that the periodic updatedb file system scans keep the atime of directories recent.

  -m, --mtime

  Make the decision about deleting a file based on the file's mtime (modification time) instead of the atime.

  -c, --ctime

  Make the decision about deleting a file based on the file's ctime (inode change time) instead of the atime; for

  directories, make the decision based on the mtime.

  -----------------------------------

  我們看到, -c 參數是使用文件的inode改變時間. 這就意味著三個參數結合使用, 最后其實僅僅是 -c 參數發揮了作用.

  以上的解釋比較廢話, 其實發生問題關鍵原因是java進程的數據文件被刪除了. 這些工具其實都能實現刪除文件的時候排除某些文件/文件夾的功能. 這樣就能避免發生錯誤刪除. 比如排除/tmp/hsperfdata_$USER 文件夾. 我們作了點小小的測試:

  1. 如果java程序是正常退出, /tmp/hsperfdata_$USER/$JAVA_PID 文件是能被正常清理

  2. 如果java程序是非正常退出, 比如使用kill -9 等辦法, 那麼pid文件將會殘留在目錄里. 但是, 如果你執行任意一次java命令, 或者載入了jvm程序的命令(比如jps, javac, jstat), 所有無用的pid文件都能被正確的清理.

  一句話, jvm能夠自己管理/tmp/hsperfdata_$USER 下的文件有效性. 不用擔心殘留pid文件過多的情況.

  附錄

  redhat修改文件:

  /etc/cron.daily/tmpwatch

  tmpwatch shell 寫道

  flags=-umc

  /usr/sbin/tmpwatch "$flags" -x /tmp/hsperfdata_$YOUR_USER_NAME -x /tmp/.X11-unix -x /tmp/.XIM-unix

  -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix 240 /tmp

  /usr/sbin/tmpwatch "$flags" 720 /var/tmp

  for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do

  if [ -d "$d" ]; then

  /usr/sbin/tmpwatch "$flags" -f 720 "$d"

  fi

  done


[火星人 ] Java長期運行后, jps等工具無法連接jvm已經有787次圍觀

http://coctec.com/docs/java/show-post-60584.html