在 Java 中创建 MBean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25308744/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 07:49:36  来源:igfitidea点击:

Creating MBean in Java

javajmxmbeans

提问by Biscuit128

I am trying to make a class implement an MBean Interface so I can interrogate the properties at runtime. The class I am trying to interrogate is as follows

我试图让一个类实现一个 MBean 接口,以便我可以在运行时查询属性。我试图询问的课程如下

public class ProfileCache implements ProfileCacheInterfaceMBean{

    private Logger logger = Logger.getLogger(ProfileCache.class);
    private ConcurrentMap<String, Profile> cache;


    public ProfileCache(ConcurrentMap<String, Profile> cache){
        this.cache = cache;     
    }

    /**
     * Update the cache entry for a given user id
     * @param userid the user id to update for 
     * @param profile the new profile to store
     * @return true if the cache update
     */
    public boolean updateCache(String userid, Profile profile) {
        if (cache == null || cache.size() == 0) {
            throw new RuntimeException("Unable to update the cache");
        }
        if (cache.containsKey(userid)) {
            if (profile != null) {
                cache.put(userid, profile);
                logger.info("Updated the cache for user: "
                            + userid + "  profile: " + profile);
                return true;
            }
        }
        return false;
    }

    @Override
    public ConcurrentMap<String, Profile> getCache() {
        if(cache == null){
            cache = new ConcurrentHashMap<String, Profile>();
        }
        return cache;
    }


}

The interface looks like this

界面是这样的

import com.vimba.profile.Profile;

public interface ProfileCacheInterfaceMBean {

    ConcurrentMap<String, Profile> getCache();

}

And i start the MBean like this

我像这样启动 MBean

        cacheImpl = new ProfileCache(factory.createCacheFromDB());
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        ObjectName profileCache = new ObjectName("org.javalobby.tnt.jmx:type=ProfileCacheInterfaceMBean");  
        mbs.registerMBean(cacheImpl, profileCache);

However i keep getting the below exception and I am not sure what I need to change

但是我不断收到以下异常,我不确定我需要改变什么

javax.management.NotCompliantMBeanException: MBean class com.vimba.cache.ProfileCache does not implement DynamicMBean, and neither follows the Standard MBean conventions (javax.management.NotCompliantMBeanException: Class com.vimba.cache.ProfileCache is not a JMX compliant Standard MBean) nor the MXBean conventions (javax.management.NotCompliantMBeanException: com.vimba.cache.ProfileCache: Class com.vimba.cache.ProfileCache is not a JMX compliant MXBean)

I think potentially it's because it returns a Map?

我认为可能是因为它返回了一个 Map?

回答by Bjorn Sayers

Having just encountered this exception and looked at the current answers as well as https://blogs.oracle.com/jmxetc/entry/javax_management_standardmbean_when_andI thought it might help to emphasize and clarify the following already elucidated to:

刚刚遇到这个异常并查看了当前的答案以及https://blogs.oracle.com/jmxetc/entry/javax_management_standardmbean_when_我认为这可能有助于强调和澄清以下已经阐明的内容:

  1. The NotCompliantMBeanException is caused, among other things, by failing to follow this convention 'ConcreteClassName' implements 'ConcreteClassNameMBean'

  2. I resolved this by updating the original name of my mbean interface from 'OrignalNameMBean' to 'OriginalNameMXBean' allowing the mbean to be registered without following the convention

  3. Another solution would be to follow the convention.

  1. NotCompliantMBeanException 是由于未能遵循此约定而引起的 'ConcreteClassName' 实现了 'ConcreteClassNameMBean'

  2. 我通过将 mbean 接口的原始名称从“OrignalNameMBean”更新为“OriginalNameMXBean”来解决此问题,允许在不遵循约定的情况下注册 mbean

  3. 另一种解决方案是遵循惯例。

回答by user3044236

I had the same issue ("does not implement DynamicMBean, and neither follows the Standard MBean conventions") and this article helped me to resolve the problem (see Using StandardMBean section: https://blogs.oracle.com/jmxetc/entry/javax_management_standardmbean_when_and).

我遇到了同样的问题(“不实现 DynamicMBean,也不遵循标准 MBean 约定”),这篇文章帮助我解决了这个问题(参见使用 StandardMBean 部分:https: //blogs.oracle.com/jmxetc/entry/ javax_management_standardmbean_when_and)。

I have to explicitly construct a

我必须明确构建一个

StandardMBean mbean = new StandardMBean(mBeanImpl, MBeanInterface.class);

then register the mbean:

然后注册mbean:

mbServer.registerMBean(mbean, mBeanName);

It works.

有用。

When I register the mBeanImpl with the mbServer, I got the above exception.

当我向 mbServer 注册 mBeanImpl 时,出现上述异常。

回答by Kim Zeevaarders

The implementing mbean class can declare as many methods as it likes that are not defined in mbeans interface... There is no requirement that the implementing class can/must onlyimplement the interface methods.

实现 mbean 类可以声明任意数量的方法,但没有在 mbeans 接口中定义......没有要求实现类可以/必须实现接口方法。

In many of the cases this problem is caused because the mbean interface and implementation class are not in the same package!

在很多情况下,这个问题是因为mbean 接口和实现类不在同一个包中

回答by flahsy

You can change interface name from SomethingMBean to SomethingMXBean,such as HelloMBean to HelloMXBean,from jdk's source code i saw this:

您可以将接口名称从SomethingMBean更改为SomethingM XBean,例如HelloMBean更改为HelloMXBean,从jdk的源代码中我看到了这个:

public static boolean isMXBeanInterface(Class<?> interfaceClass) {
    if (!interfaceClass.isInterface())
        return false;
    if (!Modifier.isPublic(interfaceClass.getModifiers()) &&
        !Introspector.ALLOW_NONPUBLIC_MBEAN) {
        return false;
    }
    MXBean a = interfaceClass.getAnnotation(MXBean.class);
    if (a != null)
        return a.value();
    return interfaceClass.getName().endsWith("MXBean");
}

if not endsWith "MXBean",it will return false,then cause throw IllegalArgumentException

如果不是endsWith "MXBean",则返回false,然后导致抛出IllegalArgumentException

jdk version:1.8.0_25

jdk 版本:1.8.0_25

class is "JMX",line 376

类是“JMX”,第 376 行

回答by deenfirdoush

Just change your implementation class name from ProfileCache to ProfileCacheInterface. It should work now. Moreover your implementation class can have any number of its own methods and those methods needs not to be mentioned in the MBean interface.

只需将您的实现类名称从 ProfileCache 更改为 ProfileCacheInterface。它现在应该可以工作了。此外,您的实现类可以有任意数量的自己的方法,而无需在 MBean 接口中提及这些方法。

JMX's standard mbean naming convention is like this

JMX的标准mbean命名约定是这样的

    public interface SomeBeanNameMBean{
    ...
    }

    public class SomeBeanName implements SomeBeanNameMBean{
    ...
    //implements all the methods of SomeBeanNameMBean
    ...
    //implement other class's own methods if needed
    }

回答by jdb1015

In the all the examples I've seen for MBean implementations, I've never seen a class define a method that was not defined in the interface. E.g., ProfileCache has method updateCache, but ProfileCacheInterfaceMBean does not. Try removing the updateCache method from ProfileCache and see if it will work.

在我见过的所有 MBean 实现示例中,我从未见过类定义了未在接口中定义的方法。例如,ProfileCache 有方法 updateCache,但 ProfileCacheInterfaceMBean 没有。尝试从 ProfileCache 中删除 updateCache 方法,看看它是否有效。

回答by Hari Krishna

I faced the same problem like 'Exception in thread "main" javax.management.NotCompliantMBeanException', in my case I kept MBean interface and implementation classes in differnet package. To resolve the issue, I moved both MBean interface and the implementation class to same package.

我遇到了同样的问题,比如“线程“主”javax.management.NotCompliantMBeanException 中的异常,在我的例子中,我将 MBean 接口和实现类保留在不同的包中。为了解决这个问题,我将 MBean 接口和实现类都移到了同一个包中。

回答by u7687624

Just change interface suffix from 'MBean' to 'MXBean'. This works for me.

只需将接口后缀从“MBean”更改为“MXBean”即可。这对我有用。