【问题标题】:Accessing built-in MBeans in Tomcat programmatically以编程方式访问 Tomcat 中的内置 MBean
【发布时间】:2013-07-01 17:08:04
【问题描述】:

基本上我正在尝试修改本教程中的代码:http://docs.oracle.com/javase/tutorial/jmx/remote/custom.html 这样我就可以从这里描述的 tomcat 访问 MBean:http://wiki.apache.org/tomcat/FAQ/Monitoring

从代码中访问 JMX Bean java.lang:type=Memory 没有问题,因为它的接口是在 java.lang 中定义的。这是它的代码示例:

    ObjectName mbeanName = new ObjectName("java.lang:type=Memory");
    MemoryMXBean mxbeanProxy2 = JMX.newMXBeanProxy(mbsc, mbeanName, MemoryMXBean.class, true);
    MemoryUsage memUsage = mxbeanProxy2.getHeapMemoryUsage();
    echo("\nMemory Utilization: " + (memUsage.getUsed()/(double)memUsage.getMax()) * 100 +  "%");

这里的 mbsc 是 MBeanServerConnection 的一个实例。 问题是,当我尝试以类似的方式访问 tomcat 中的内置 MBean 时,我遇到了找不到为任何 tomcat MBean 定义的任何接口的问题。我可以从 JConsole 监视 MBean,但为此我需要能够从代码中执行此操作。我在某处发现它也可以通过以下方式完成:

ObjectName mbeanName2 = new ObjectName("Catalina:type=ThreadPool,name=\"http-apr-8080\"");
Object value = mbsc.getAttribute(mbeanName, "name");

但这给了我这个例外: 线程“主”javax.management.AttributeNotFoundException 中的异常:没有这样的属性:com.sun.jmx.mbeanserver 的名称......

我觉得我错过了一些相当基本的东西。但是这方面的信息似乎非常有限,谷歌并没有太大帮助。

【问题讨论】:

    标签: tomcat jmx mbeans


    【解决方案1】:

    我认为您的第二个 sn-p 代码中有错字。您为 Catalina ThreadPool 创建了一个名为 mbeanName2 的新 ObjectName,但是当您尝试检索属性“name”时,您仍在使用 mbeanName

    应该是这样的:

    ObjectName mbeanName2 = new ObjectName("Catalina:type=ThreadPool,name=\"http-apr-8080\"");
    Object value = mbsc.getAttribute(mbeanName2, "name");
    

    除此之外,您的代码应该可以正常工作。

    【讨论】:

    • 所以只要修正这个错字就可以了?一旦我可以验证这一点,我会接受你的回答...
    【解决方案2】:

    今天我遇到了与上述 Oz0234 相同的问题(在 Windows 上使用 TomEE 1.7.0),但我有一段时间不明白为什么 ProxyBean 解决方案根本不适用于任何 Catalina 对象。

    它适用于 MBeanServerConnection.getAttribute(objectName, attribute) 方法,但它不起作用使用 代理 bean 方法。我已经检查和测试了很多。

    我终于找到了发生这种情况的原因。答案是Catalina 域中的属性名称以小写字母开头,而其他域(java.lang、java.nio、openejb、...)中的属性名称以大写字母开头大小写字母如下所述:http://docs.oracle.com/javase/7/docs/api/javax/management/JMX.html

    我提取了最相关的部分:

    MyMXBean proxy = JMX.newMXBeanProxy(mbs, name, MyMXBean.class);
    

    假设,例如,MyMXBean 看起来像这样:

    public interface MyMXBean {
      public String getSimpleAttribute();
      public void setSimpleAttribute(String value);
      public MemoryUsage getMappedAttribute();
      public void setMappedAttribute(MemoryUsage memoryUsage);
      public MemoryUsage someOperation(String param1, MemoryUsage param2);
    }
    
    Then proxy.getSimpleAttribute() will result in a call to
    mbs.getAttribute(name, "SimpleAttribute").
    

    可以看到上面的例子,属性名以大写字母“S”impleAttribute作为代理bean getter name getSimpleAttribute。不幸的是,这与 bean 的 getter/setter 命名约定所描述的完全相反。

    我还检查了 JMX 连接上可用的其他 Tomcat 域对象 (Catalina,Users) 属性,并且我还比较了其他一些属性。如果属性名称以大写字母开头,则 bean 代理工作。如果它以小写字母开头,则只有 getAttribute 方法有效,如下所示:

    JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
    try(JMXConnector jmxc = JMXConnectorFactory.connect(url)) {
      MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
      ObjectName mbeanName = new ObjectName("Catalina:type=Manager,context=/,host=localhost");
      Object value = mbsc.getAttribute(mbeanName, "activeSessions");
    }
    

    所以你需要注意你选择哪种方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      • 2017-04-30
      • 2010-12-13
      • 1970-01-01
      • 2010-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多