java – 使用jmx的动态代理可能导致线程泄漏?

我在 Java中遇到问题,我在其中设置了一个带有JMX接口的动态代理,将其传递给另一个组件,然后调用代理对象.当我这样做时,应用程序为每个调用泄漏两个线程,线程似乎永远不会超时并继续构建,直到应用程序内存不足.

线程成对出现,请参见底部的stacktrace.

我曾尝试使用一些稍微模糊的系统属性来完全关闭JMX中的超时但它并没有什么区别.关键动作似乎是动态代理调用.通过代理调用的对象实现Serializable,因此不应该是一个问题.

当我手动创建一个包含MBean路径和对象接口的字符串的Bean并从中调用方法时,问题就消失了.

因为我对它们没有太多的经验,所以我主要在寻找动态代理的经典问题.

这就是创建proxyinstance的方式

public <T> T create(final Class<T> type,final Object... nameParameters) throws JmxConnectionException {
    return type.cast(Proxy.newProxyInstance(
            type.getClassLoader(),new Class< ? >[] {type},new MyInvocationHandler(this,fill(nameOf(type),nameParameters))));
}

和MyInvocationHandler的实现:

final class MyInvocationHandler implements InvocationHandler,Serializable {
private static final long serialVersionUID = 0L; //actually a proper random long
private final transient ProxyFactory proxyFactory;
private String mBeanName;
private RemoteObject remoteObject;

MyInvocationHandler(final ProxyFactory proxyFactory,final String mBeanName) {
    this.proxyFactory = proxyFactory;
    this.mBeanName = mBeanName;
}

private void writeObject(final ObjectOutputStream out)
throws IOException {
    try {
        checkConnected();
    } catch (final JmxConnectionException e) {
        throw new IOException(e);
    }
    out.writeObject(mBeanName);
    out.writeObject(remoteObject);
}

private void readobject(final ObjectInputStream in)
throws IOException,ClassNotFoundException {
    mBeanName = (String) in.readobject();
    remoteObject = (RemoteObject) in.readobject();
}

public Object invoke(final Object proxy,final Method method,final Object[] args) throws Throwable {
    checkConnected(); //Just checks that the RemoteObject isn't null.
    try {
        return invokeMethod(method,args); // Calls the method on the remoteObject with the arguments,code cut.
    } catch (final InvocationTargetException e) {
        throw e.getCause();
    }
}

}

两个线程的线程堆栈跟踪(总是成对出现):

Name: JMX server connection timeout 53
State: TIMED_WAITING on [I@18bbe70
Total blocked: 3  Total waited: 4

Stack trace: 
java.lang.Object.wait(Native Method)
com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:150)
java.lang.Thread.run(Thread.java:619)

Name: Thread-21
State: TIMED_WAITING
Total blocked: 0  Total waited: 1

Stack trace: 
java.lang.Thread.sleep(Native Method)
com.sun.jmx.remote.internal.ClientCommunicatorAdmin$Checker.run(ClientCommunicatorAdmin.java:154)
java.lang.Thread.run(Thread.java:619)

解决方法

问题已经解决了.在RemoteObject下面的对象序列化过程中出现问题.

当你创建一个JMXConnector时,确保在你完成使用它时关闭它,而不是把它留给垃圾收集,或者看起来它们可以继续堆积……

JMXConnector connector = JMXConnectorFactory.connect(url);
//...
connector.close();

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...