2009-02-19 58 views
7

我在Java中有一個問題,我使用JMX接口設置動態代理,將其傳遞給另一個組件,然後調用代理對象。當我這樣做時,應用程序會爲每個調用泄漏兩個線程,這些線程永遠不會超時,並在應用程序內存不足時繼續構建。使用jmx的動態代理會導致線程泄漏?

線程成對出現,請參閱底部的堆棧跟蹤。

我曾嘗試使用一些稍微模糊的系統屬性來關閉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 [[email protected] 
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) 

回答

12

問題已解決。在RemoteObject下面的對象的序列化過程中出現此問題。

當你創建一個JMXConnector,請務必關閉它,當你使用它,而不是留給了垃圾收集完成,或似乎可以保持堆放...

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

多麼的幸運我搜索了`com.sun.jmx.remote.internal.ClientCommunicatorAdmin`,並首先找到了這個答案。 – 2014-06-25 04:50:22