2009-02-19 4 views
7

J'ai un problème en Java où je configure un proxy dynamique avec une interface JMX, transmettez-le à un autre composant qui appelle ensuite l'objet proxy. Lorsque je fais cela, l'application perd deux threads pour chaque appel, les threads qui ne semblent jamais expirer et continuer à construire jusqu'à ce que l'application manque de mémoire. Les threads apparaissent par paires, voir stacktrace dans la partie inférieure.les proxies dynamiques avec jmx peuvent provoquer des fuites de fil?

J'ai essayé d'utiliser certaines propriétés système légèrement obscures pour désactiver tous les délais d'attente dans JMX mais cela ne fait aucune différence. L'action clé semble être l'appel proxy dynamique. L'objet appelé via le proxy implémente Serializable, ce qui ne devrait pas poser de problème.

Lorsque je crée manuellement un bean avec une chaîne du chemin MBean et l'interface d'objet et appelez la méthode à partir de cela, le problème disparaît.

Je suis surtout à la recherche de pièges classiques quand il s'agit de proxies dynamiques, car je n'ai pas trop d'expérience avec eux.

Voici comment le proxyinstance est créé

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

et la mise en œuvre de 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(); 
    } 
} 

}

Discussion stacktrace pour les deux fils (apparaissent toujours par paires):

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) 

Répondre

12

Le problème a été résolu. Le problème apparaît lors de la sérialisation d'un objet sous RemoteObject.

Lorsque vous créez un JMXConnector, assurez-vous de le fermer lorsque vous avez terminé de l'utiliser plutôt que de le laisser à la collecte des ordures, ou il semble qu'ils peuvent garder empiler ...

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

la chance J'ai cherché 'com.sun.jmx.remote.internal.ClientCommunicatorAdmin' et j'ai trouvé cette réponse en premier. –

Questions connexes