行为MBeanServerForwarder(Behavior MBeanServerForward

2019-09-16 10:08发布

我曾问一个问题在这里 ,但我没有得到答案。 Howerver,我继续我的搜索,我发现有些东西就是取悦我的需要:“MBeanServerForwarder”。 我读了官方的JavaDoc,但它仍不清楚我。

那么,这是否MBeanServerForwarder工作作为一个MBeanServer的代理? 即:我可以用它来拦截MBean的注册表,使在对象名的修改,并将其转发到MBeanServer?

提前致谢。

Answer 1:

是的,但它是不是真的有必要。 你只需要实现MBeanServer接口并重写registerMBean方法(也许是unregisterMBean方法)。

使用真正的MBeanServer作为一个代表,这里是你的实现可能是什么样子:

    public class AltObjectNameMBeanServer implements MBeanServer {
        protected final MBeanServer innerServer;
        protected final ObjectName filter;

        public AltObjectNameMBeanServer(MBeanServer innerServer, ObjectName filter) {
            this.innerServer = innerServer;
            this.filter = filter;
        }

        public ObjectInstance registerMBean(Object object, ObjectName name) throws InstanceAlreadyExistsException,
                MBeanRegistrationException, NotCompliantMBeanException {
            if(filter.apply(name)) {
                name = reformat(name);          
            }
            return innerServer.registerMBean(object, name);
        }

        public static ObjectName reformat(ObjectName on) 
            try {
                int id = on.toString().hashCode();
                return new ObjectName(new StringBuilder(on.toString()).append(",serial=").append(id).toString());

            } catch (Exception e) {
                throw new RuntimeException("Failed to reformat [" + on + "]", e);
            }
        }

     // ======== Put direct delegates for all other methods =======

}

用法示例:

        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        AltObjectNameMBeanServer rr = new AltObjectNameMBeanServer(server, new ObjectName("*:*"));          
        Class clazz = Class.forName("sun.management.HotspotInternal");
        HotspotInternalMBean obj = (HotspotInternal)clazz.newInstance();
        ObjectInstance oi = rr.registerMBean(new StandardMBean(obj, HotspotInternalMBean.class), new javax.management.ObjectName("sun.management:type=HotspotInternal"));
        System.out.println("ObjectName:" + oi.getObjectName());

输出是:

的ObjectName:sun.management:类型= HotspotInternal,串行= -441253090

带着几分反思,你可以设置你的新的MBeanServer IMPL。 在java.lang.management.ManagementFactoryplatformMBeanServer领域,你将永久重写了JVM代理的MBean注册。

==========更新============

这段代码演示了如何可能使用AltObjectNameMBeanServer的RR实例从上面砍平台MBeanServer提供备用(或包裹)的MBeanServer(:

Field serverField = ManagementFactory.class.getDeclaredField("platformMBeanServer");
serverField.setAccessible(true);
serverField.set(null, rr);
System.out.println("Equal:" + (rr==ManagementFactory.getPlatformMBeanServer()));

==========更新============

这里是什么,我认为你正在寻找一个简单的例子。 见这个要点 。

如果您用这些选项的例子:

-Djavax.management.builder.initial=org.helios.jmx.HeliosMBeanServerBuilder
-Dhelios.jmx.renamer.filter=java.util.logging:*

它会覆盖系统默认的MBeanServerBuilder和拦截匹配的java.util.logging ObjectName的所有MBean的注册:*。

运行时,它会打印所有的平台MBeanServer的MBean的ObjectName和输出看起来就像这样:

MBeanServer Interceptor Test
java.lang:type=MemoryPool,name=PS Eden Space
java.lang:type=Memory
java.lang:type=MemoryPool,name=PS Survivor Space
java.lang:type=GarbageCollector,name=PS MarkSweep
java.lang:type=MemoryPool,name=Code Cache
java.lang:type=Runtime
java.lang:type=ClassLoading
java.lang:type=Threading
java.lang:type=Compilation
com.sun.management:type=HotSpotDiagnostic
java.lang:type=MemoryPool,name=PS Perm Gen
java.util.logging:type=Logging,serial=-132046985
java.lang:type=OperatingSystem
java.lang:type=GarbageCollector,name=PS Scavenge
java.lang:type=MemoryPool,name=PS Old Gen
java.lang:type=MemoryManager,name=CodeCacheManager
JMImplementation:type=MBeanServerDelegate

注意java.util.logging中的重命名:类型=记录,串行= -132046985

另外,您也可以创建自己的HeliosMBeanServer建设者的情况下,定义域名,过滤器和重命名策略,并创建自己的MBeanServer,而不是使用平台MBeanServer。



Answer 2:

由于尼古拉斯。

MBean的注册拦截

我使用代理来拦截与调用句柄和调用上下文来BeanServer所有呼叫。 我用了几个拦截器来编辑参数(例如registerMBean参数)调用方法之前和它的作品。

设置的MBeanServer作为platformMBeanServer

  1. 尼古拉斯的方法(看他的帖子)
  2. 使用定制的MBeanServerBuilder

为此,我们要设置一个系统属性:

-Djavax.management.builder.initial=my.own.MBeanServerBuilder

你可能会得到一个NotFoundClassException。 为了解决这个问题,确保Thread.CurrentThread()的类加载器是比创建的MBeanServer类相同。

你自己的MBeanServerBuilder必须扩展的MBeanServerBuilder类。 根据您的需求,覆盖的方法来添加信息。 对于我的使用情况下,我只好返回的MBeanServer的代理,所以我创建一个新的MBeanServer,创建代理并将其返回。

public MBeanServer newMBeanServer(String              defaultDomain,
                                  MBeanServer         outer,
                                  MBeanServerDelegate delegate) {

    MBeanServer origin = super.newMBeanServer(defaultDomain, outer, delegate);
    return (MBeanServer) Proxy.newProxyInstance(origin.getClass().getClassLoader(), new Class<?>[]{MBeanServer.class}, handler);

}


文章来源: Behavior MBeanServerForwarder
标签: jmx mbeans