java - 带有 jmx 的动态代理会导致线程泄漏?

标签 java multithreading jmx proxy-classes

我在使用 JMX 接口(interface)设置动态代理的 Java 中遇到问题,将其传递给另一个组件,该组件然后调用代理对象。当我这样做时,应用程序会为每次调用泄漏两个线程,这些线程似乎永远不会超时并不断增加,直到应用程序内存不足。

线程成对出现,查看底部的堆栈跟踪。

我曾尝试使用一些稍微晦涩的系统属性来关闭 JMX 中的所有超时,但这并没有什么不同。关键操作似乎是动态代理调用。通过代理调用的对象实现了 Serializable,所以这应该不是问题。

当我用 MBean 路径和对象接口(interface)的字符串手动创建 Bean 并从中调用方法时,问题就消失了。

当涉及到动态代理时,我主要在这里寻找经典陷阱,因为我对它们没有太多经验。

代理实例是这样创建的

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

关于java - 带有 jmx 的动态代理会导致线程泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/564589/

相关文章:

java - 在调用查询此持久化实体的另一个线程之前,如何确保实体已持久化?

java - MBeans操作错误Weblogic

java - 如何在远程 jmx URL 的 java 中获取所有垃圾收集器 MX bean?

java - 如何在jconsole中自动刷新JMX属性

Java Socket 在不同机器上不起作用

java - 类的静态方法之间的同步

java - 通过查找表更改数据

c++ - 加快 CSV 文件的处理速度

Java - 查找 Cookie 是否被禁用

java - 如何启用 checkstyle 的 MissingOverride 检查?