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