Behavior MBeanServerForwarder

无人久伴 提交于 2019-12-08 10:44:58

问题


I have asked a question here but I did not get an answer. Howerver, I continue my search and I found something which could please my need : "MBeanServerForwarder". I read the official JavaDoc but it is still not clear for me.

So, does MBeanServerForwarder work as a proxy for a MBeanServer? ie: Can I use it to intercept MBeans registry, make modification in the ObjectName and forward it to the MBeanServer?

Thanks in advance.


回答1:


Yes, but it's not really necessary. You only need to implement the MBeanServer interface and override the registerMBean method (and perhaps the unregisterMBean method).

Using the real MBeanServer as a delegate, here's what your implementation might look like:

    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 =======

}

Sample usage:

        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());

The output is:

ObjectName:sun.management:type=HotspotInternal,serial=-441253090

With a bit of reflection, you could set your new MBeanServer impl. in the platformMBeanServer field of the java.lang.management.ManagementFactory and you will have permanently overriden the JVM agent's MBean registration.

========== Update ============

This code snippet demonstrates how you might hack the platform MBeanServer to supply an alternate (or wrapped) MBeanServer (using the rr instance of AltObjectNameMBeanServer from above:

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

========== Update ============

Here's a simple example of what I think you are looking for. See this gist.

If you run the example with these options:

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

It will override the system's default MBeanServerBuilder and intercept all MBean registrations with ObjectNames matching java.util.logging:*.

When the main runs, it will print all the platform MBeanServer MBean ObjectNames and the output will look like this:

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

Note the renaming of java.util.logging:type=Logging,serial=-132046985

Alternatively, you can create your own instance of the HeliosMBeanServer builder, define the domain name, the filter and the rename strategy and create your own MBeanServer rather than using the platform MBeanServer.




回答2:


Thanks to Nicholas.

MBeans registration interception

I used a Proxy to intercept all calls to BeanServer with Invocation Handler and Invocation Context. I used several interceptors to edit parameters (registerMBean parameters for example) before invoking the method and it works.

Set MBeanServer as platformMBeanServer

  1. Nicholas's method (see his post)
  2. Use customized MBeanServerBuilder

For that, we have to set a system property :

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

You will probably get an NotFoundClassException. To deal with this, ensure that the classloader of Thread.CurrentThread() is the same than the class which create the MBeanServer.

Your own MBeanServerBuilder must extend MBeanServerBuilder class. Depending in your needs, override method to add information. For my use case, I had to return a proxy of the MBeanServer, so I create a new MBeanServer, create the proxy and return it.

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);

}


来源:https://stackoverflow.com/questions/10070769/behavior-mbeanserverforwarder

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!