由于项目中使用jboss 作为web容器,每当项目上线时需要使用loadrunner对项目进行性能压测,这时就需要实时观察JVM的一些参数。想使用jvisualvm借助jstatd远程连接服务器上面的JVM时一直不能成功
在网上找了好些资料都始终没有成功,最终通过阅读jdk的相关源码终于使得jvisualvm借助jstatd能远程连接jboss。特写这篇博文记录解决问题过程。
当在命令中输入 jstatd时会出现如下错误:
找网上找许多资料对该错误的解决如下,实际上按照这样进行操作依然没有解决该错误。
创建安全策略文件,并命名为jstatd.all.policy
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
通过阅读Jstatd的源码发现引起该错误的原因是为在该类的第139行调用了
System.setProperty("java.rmi.server.ignoreSubClasses", "true");
根据java安全沙盒机制,需要在jstatd.all.policy配置文件中添加如下内容:
grant {
permission java.util.PropertyPermission "java.rmi.server.ignoreSubClasses","write";
};
所以完整的 jstatd.all.policy 配置文件如下
grant codebase "file:${java.home}/../lib/tools.jar" { permission java.security.AllPermission; }; grant { permission java.util.PropertyPermission "java.rmi.server.ignoreSubClasses","write"; };
当解决上面的问题后,通过jvisualvm远程连接服务器上的jstatd一直连接不上。通过阅读jdk的rmi注册源码 发现有这么一行代码:
1 try { 2 host = java.net.InetAddress.getLocalHost().getHostAddress(); 3 } catch (Exception e) { 4 // If that failed, at least try "" (localhost) anyway... 5 host = ""; 6 }
这代码是获取本地IP地址。如果不在本机host文件中添加本机机器名对应的IP 则这行代码将返回127.0.0.1 这也导致了jvisualvm无法远程连接jstatd。
下面是完整的步骤
进入到jdk安装目录下,在/usr/java/jdk1.6.0_45/jre/lib/security 下创建jstatd.all.policy文件,文件的内容如下:
grant codebase "file:${java.home}/../lib/tools.jar" { permission java.security.AllPermission; }; grant { permission java.util.PropertyPermission "java.rmi.server.ignoreSubClasses","write"; };
编辑/usr/java/jdk1.6.0_45/jre/lib/security路径下面的java.security文件 policy.url.3=file:${java.home}/lib/security/jstatd.all.policy 如果 policy.url.3已经存在
可以使用 policy.url.n n表示正整数。
编辑host文件中,添加对机器名称<---> ip映射
完成上面两步骤后,运行jstatd参数,因为没有指定端口,rmi默认注册使用的端口是1099 查看jstatd是否已经成功运行
出现了上面的截图,表示jstatd已经成功运行。关闭linux的防火墙。后在本机尝试使用jvisualvm远程连接jstatd。
终于 能通过jvisualvm 远程连接jboss,但是jvisualvm 中无法察看cpu和显示线程选项卡,后面还要进一步解决这个问题。
远程服务器使用的jdk的版本:
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) Client VM (build 20.45-b01, mixed mode, sharing)
远程服务器使用的jboss版本为:
jboss-eap-6.3