8

JMX インターフェイスを使用して動的プロキシを設定する Java に問題があり、これを別のコンポーネントに渡し、プロキシ オブジェクトを呼び出します。これを行うと、アプリケーションは呼び出しごとに 2 つのスレッドをリークします。これらのスレッドはタイムアウトすることはなく、アプリケーションがメモリ不足になるまで構築し続けます。

スレッドはペアで表示されます。下部のスタック トレースを参照してください。

少しあいまいなシステム プロパティを使用して、JMX でタイムアウトをまとめてオフにしようとしましたが、違いはありません。重要なアクションは、動的プロキシ呼び出しのようです。プロキシ経由で呼び出されるオブジェクトは Serializable を実装しているため、問題にはなりません。

MBean パスとオブジェクト インターフェイスの文字列を使用して手動で 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();
    }
}

}

2 つのスレッドのスレッド スタック トレース (常にペアで表示されます):

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

1 に答える 1

13

The problem has been solved. The problem appears during serialization of an object below RemoteObject.

JMXConnectorを作成するときは、ガベージ コレクションに任せるのではなく、使い終わったら閉じるようにしてください。

JMXConnector connector = JMXConnectorFactory.connect(url);
//...
connector.close();
于 2009-02-19T16:19:51.467 に答える