我正在尝试编写一个客户端实用程序,通过JMX连接到Tomcat,并查看连接数据源的状态。 我在$ CATALINA_HOME / bin / setenv.bat中设置了以下VM参数并重新启动了Tomcat
设置JAVA_OPTS = -Xms512M -Xmx1024M -XX:MaxPermSize = 256M%JAVA_OPTS% 设置CATALINA_OPTS = -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port = 9004 -Dcom.sun.management.jmxremote.authenticate = false -Dcom.sun.management.jmxremote.ssl = false%CATALINA_OPTS%
我对JMX不太熟悉所以我只是想玩它来感受它。 我写的实用程序将在Tomcat之外运行。我编写了以下测试来尝试访问Tomcat中的数据源Mbean对象 但由于某种原因,它没有找到它。
public class GuiMonitor {
public static void main(String[] args){
try{
JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
final List<MBeanServer> servers = new LinkedList<MBeanServer>();
servers.add(ManagementFactory.getPlatformMBeanServer());
servers.addAll(MBeanServerFactory.findMBeanServer(null));
System.out.println("MbeanServers " + servers.size());
for(final MBeanServer server : servers){
System.out.println("Server : " + server.getClass().getName());
}
MBeanServer mbsc = ManagementFactory.getPlatformMBeanServer();
System.out.println(mbsc.queryMBeans(null, null));
ObjectName on = new ObjectName("Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\"");
System.out.println("ObjectName : " + on.toString());
System.out.println(mbsc.getAttribute(on, "Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\""));
} catch (Exception e) {
e.printStackTrace();
}
}
}
我有一个我在互联网上找到的JSP页面,当我上传到webapps文件夹并运行它时,它会显示所有可用的 Tomcat中的MBean。我上面使用的对象字符串/名称来自我使用的jsp页面和Jconsole上报告的名称,因此它确实存在。
上述程序的输出如下所示
MbeanServers 2
Server : com.sun.jmx.mbeanserver.JmxMBeanServer
Server : com.sun.jmx.mbeanserver.JmxMBeanServer
[com.sun.management.OperatingSystem[java.lang:type=OperatingSystem], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Tenured Gen], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Perm Gen], java.util.logging.Logging[java.util.logging:type=Logging], sun.management.CompilationImpl[java.lang:type=Compilation], javax.management.MBeanServerDelegate[JMImplementation:type=MBeanServerDelegate], sun.management.MemoryImpl[java.lang:type=Memory], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Survivor Space], sun.management.RuntimeImpl[java.lang:type=Runtime], sun.management.GarbageCollectorImpl[java.lang:type=GarbageCollector,name=Copy], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Eden Space], sun.management.GarbageCollectorImpl[java.lang:type=GarbageCollector,name=MarkSweepCompact], sun.management.ThreadImpl[java.lang:type=Threading], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Perm Gen [shared-ro]], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Perm Gen [shared-rw]], sun.management.HotSpotDiagnostic[com.sun.management:type=HotSpotDiagnostic], sun.management.ClassLoadingImpl[java.lang:type=ClassLoading], sun.management.MemoryManagerImpl[java.lang:type=MemoryManager,name=CodeCacheManager], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Code Cache]]
ObjectName : Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name="jdbc/appdb"
javax.management.InstanceNotFoundException: Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name="jdbc/appdb"
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1094)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:662)
at com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:638)
at com.bt.c21.c21mon.C21GuiMonitor.main(C21GuiMonitor.java:39)
几个问题
我感觉这是连接到不同的MBeanServer。我怀疑这是因为如果你看一下mbsc.queryMBeans(null,null)的输出,就没有特定的tomcat。我用于Tomcat实例的服务名称是什么?
如果网址正确,那么服务名称是否始终为jmxrmi?为什么它找不到“Catalina:type = DataSource,path = / appdb,host = localhost,class = javax.sql.DataSource,name = \”jdbc / appdb \“”条目?
我已经看到很多如何做到这一点的例子,大多数人使用不同的方法来获取MbeanServer。我见过的几个例子是
ManagementFactory.getPlatformMBeanServer() MBeanServerFactory.findMBeanServer(空) getMBeanServerConnection()
如前所述,我正在编写的实用程序是一个普通的java应用程序,它将在tomcat之外运行。我有没有错过任何其他配置?我一直在看几个例子,大多数人都在谈论创建MBean,并且通常会引用Listeners。由于我没有创建任何新的Mbeans但只读取现有的值,我是否需要配置一个监听器?
似乎getPlatformMbeanServer()没有返回正确的JVM实例。我尝试了以下
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
System.out.println("Query2 : " + conn.queryMBeans(null, null));
这确实返回了一些Tomcat特定的值。但我仍然无法获得jdbc / appdb数据源。
krtek - 我无法使用JMX控制台,因为我打算手动完成所有操作以实现自动化。
好的,我弄明白我做错了什么。最初我试图将值检索为
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
ObjectName on = new ObjectName("Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\"");
mbsc.getAttribute(on, "Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\""));
以上是错误的,因为mbsc.getAttribute的第二个参数应该是Mbean中的属性而不是String名称。
这给了我正确的属性值
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
ObjectName on = new ObjectName("Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\"");
mbsc.getAttribute(on, "numIdle")
我还将我使用的MBeanServer从getPlatformMbeanServer()更改为getMBeanserverConnection()。我必须承认我不太了解其中的区别,因为Tomcat与getPlatformMbeanServer()返回的JVM运行在同一个JVM上。这是否意味着getPlatformMbeanServer()只返回特定于Sun的Mbeans?和getMBeanserverConnection()将包括两者?
谢谢
答案 0 :(得分:4)
那是因为您正在为您的客户端JVM获取JMX服务器的实例,而不是Tomcat实例。
这是对的:
JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
但是你应该继续这样的事情:
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
Set result = conn.queryMBeans(null,
"Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource");
要测试查询字符串,请使用JMX console等工具。