自从公司应用大部分迁移到了jetty后,一些杂七杂吧的问题,陆续的冒上来。 前段时间有很多人问我使用了jetty之后,对应的jps功能无法正常使用,jinfo/jstack等等这些命令都正常。
java进程启动后,会在$TMP(%TMP%)/hsperfdata_$username 创建一个perfData数据,用于jvmstat一些统计数据(可以看一下神人的神帖:http://rednaxelafx.iteye.com/blog/796343)。
可以做个尝试, 启动一个main函数:
public class InstrumentServer { private String ip; private String port; public InstrumentServer(String ip, String port){ this.ip = ip; this.port = port; } public int start(String ip, String port) { System.out.println("start at : " + ip + ":" + port); return 123; } public void stop() { this.ip = null; this.port = null; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getPort() { return port; } public void setPort(String port) { this.port = port; } public static void main(String args[]) throws Exception { for (int i = 0; i < 1000; i++) { InstrumentServer server = new InstrumentServer(String.valueOf(i), String.valueOf(i)); server.start(String.valueOf(i), String.valueOf(i)); Thread.sleep(1000); server.stop(); } } }
jvm参数:
-XX:-UsePerfData
几个现象:
1. 这时/tmp/hsperfdata_$username 下发现没有对应的java进程的文件
2. jps发现没有对应该main函数的进程信息
3. jinfo,jstack,jmap均可以使用,jstat功能不能使用(gc信息获取)
关于该jvm参数的,可以查看http://stackoverflow.com/questions/76327/how-can-i-prevent-java-from-creating-hsperfdata-files
最后回过头,看一下最初的问题,为啥jps失效
war解压临时目录算法如下: /** * Get a temporary directory in which to unpack the war etc etc. * The algorithm for determining this is to check these alternatives * in the order shown: * * <p>A. Try to use an explicit directory specifically for this webapp:</p> * <ol> * <li> * Iff an explicit directory is set for this webapp, use it. Do NOT set * delete on exit. * </li> * <li> * Iff javax.servlet.context.tempdir context attribute is set for * this webapp && exists && writeable, then use it. Do NOT set delete on exit. * </li> * </ol> * * <p>B. Create a directory based on global settings. The new directory * will be called "Jetty_"+host+"_"+port+"__"+context+"_"+virtualhost * Work out where to create this directory: * <ol> * <li> * Iff $(jetty.home)/work exists create the directory there. Do NOT * set delete on exit. Do NOT delete contents if dir already exists. * </li> * <li> * Iff WEB-INF/work exists create the directory there. Do NOT set * delete on exit. Do NOT delete contents if dir already exists. * </li> * <li> * Else create dir in $(java.io.tmpdir). Set delete on exit. Delete * contents if dir already exists. * </li> * </ol> **/
最后jps根本不可能知道要去哪里找这个目录,除非在一个固定的目录中查找这 个文件的指示,那还如直接在那个固定的目录直接写pid,之前的$TMP(%TMP%)/hsperfdata_${username},相对jvm来说,它就是一个固定的目录。而现在却可以根据参数改变,但JPS无法知道这个参数,所以无法获取PID。
对应的jdk bug描述: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7021676
众所周知,linux下/tmp/目录下的文件会被进行定时删除,那是不是/tmp/hsperfdata_${username},也存在同样的风险? 过一段时间后,对应的jps和jstat功能都会出现不可用。
redhat下有tmpwatch任务进行控制,在/etc/cron.daily/tmpwatch有对应的脚本,可以设置排查下对应的/tmp/hsperfdata_*的目录的清理工作,让jvm自己来保证,保证jps,jstat命令的可用
具体可以看一下, http://sdh5724.iteye.com/blog/600803