2009-04-28 5 views
6

Je voudrais en quelque sorte se connecter chaque fois que Thread.interrupt() est appelée, en enregistrant quel thread a émis l'appel (et sa pile actuelle) ainsi que des informations d'identification sur le thread qui est interrompu.Est-il possible en Java de se connecter * chaque * interruption de thread?

Existe-t-il un moyen de le faire? En cherchant des informations, j'ai vu quelqu'un faire référence à la possibilité de mettre en place un gestionnaire de sécurité. Est-ce que cela peut être fait à l'exécution (par exemple, dans un client Applet ou Web Start), ou devez-vous utiliser la JVM installée pour cela?

Ou y a-t-il une meilleure façon de faire cela?

+0

Je peux penser à quelques façons de le faire avec une complexité différente et des performances différentes. Est-ce une chose ponctuelle de trouver un bug ou est-ce quelque chose que vous voulez en production? – Fredrik

+0

Ceci est principalement quelque chose que je veux comme une chose ponctuelle, mais quelque chose que je sais que je vais vouloir utiliser de temps en temps. Si elle était assez amicale, je la laisserais dans le code de production, mais désactivée comme un mode supplémentaire de débogage à distance (via les journaux) à utiliser en cas de besoin. – Eddie

Répondre

9

En tant que hack, ce fut un beaucoup plus facile à faire que ce que je pensais que ce serait. Depuis c'est un hack rapide, je ne fais pas les choses comme faire en sorte que la trace de la pile est assez profond avant déréférencement du tableau, etc. J'inséré ce qui suit dans mon signé constructeur de Applet:

log.info("Old security manager = " + System.getSecurityManager()); 
System.setSecurityManager(new SecurityManager() { 
     @Override 
     public void checkAccess(final Thread t) { 
     StackTraceElement[] list = Thread.currentThread().getStackTrace(); 
     StackTraceElement element = list[3]; 
     if (element.getMethodName().equals("interrupt")) { 
      log.info("CheckAccess to interrupt(Thread = " + t.getName() + ") - " 
        + element.getMethodName()); 
      dumpThreadStack(Thread.currentThread()); 
     } 
     super.checkAccess(t); 
     } 
    }); 

et la méthode dumpThreadStack est la suivante:

public static void dumpThreadStack(final Thread thread) { 
    StringBuilder builder = new StringBuilder('\n'); 
    try { 
    for (StackTraceElement element : thread.getStackTrace()) { 
     builder.append(element.toString()).append('\n'); 
    } 
    } catch (SecurityException e) { /* ignore */ } 
    log.info(builder.toString()); 
} 

Je ne pourrais jamais, bien sûr, laisser cela dans le code de production, mais il suffisait de me dire exactement ce qui était à l'origine un fil interrupt() que je ne m'y attendais pas. C'est-à-dire, avec ce code en place, j'obtiens un vidage de pile pour chaque appel à Thread.interrupt().

+1

Notez que dans certaines versions de java, le SecurityManager devrait également remplacer les méthodes checkPermission (pour l'option la plus permissive et la plus simple, les retourner simplement) ou bien vous pouvez rencontrer des erreurs de sécurité comme 'java.security.AccessControlException: access denied'. – vazor

4

Avant d'essayer quelque chose de trop sauvage, avez-vous envisagé d'utiliser le Java debuggingAPI? Je pense que capturer MethodEntryEvents sur Thread.interrupt() le ferait. Eey, c'est l'ancienne interface, vous devriez également vérifier sur le nouveau JVM ToolInterface.

+0

Je suis vaguement conscient de l'API de débogage Java, mais je ne suis pas sûr de savoir comment l'utiliser dans l'application sur laquelle je l'utiliserais. – Eddie

+0

Je vous ai donné quelques liens maintenant; la réponse courte est que vous ajoutez un indicateur à l'appel JVM, puis vous pouvez vous connecter à la JVM en externe. –

+0

Malheureusement, vos suggestions ne m'aideront pas. La nouvelle interface d'outil JVM nécessite JNI et l'ancienne API de débogage Java n'est pas disponible pour Applets. Cependant, cette information peut s'avérer utile pour quelque chose d'autre à l'avenir. Merci pour les pointeurs. – Eddie

2

Je voudrais regarder AspectJ et ses capacités à emballer les appels de méthode. Un execution pointcut autour de la méthode interrupt() devrait aider ici.

Notez que puisque vous cherchez à intercepter un appel de méthode système Java (par opposition à votre code d'application), le ci-dessus ne peut pas convenir. This thread semble suggérer que c'est possible, mais notez qu'il a créé un tissé rt.jar.

+0

Vous pouvez même intégrer des méthodes dans les bibliothèques JVM? – Eddie

+0

C'est un bon point, et un que je considérais juste comme je l'ai tapé. Il y a différents mécanismes de byte-weaving, certainement (temps de compilation/temps d'exécution/temps de chargement de la classe) donc l'un d'entre eux peut fonctionner. –

0

Vous pouvez également essayer avec JMX:

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID) 

avec l'objet ThreadInfo vous pouvez vous connecter:

  • la trace de la pile du fil
  • informations Userful générales comme le nom, le statut, etc.
  • etc.

EDIT

getAllThreadIds d'utilisation() afin d'obtenir la liste des ids de fil en direct:

long[] ids = ManagementFactory.getThreadMXBean().getAllThreadIds(); 
+0

Comment voulez-vous dire que ce serait attraper l'interruption-appel? – Fredrik

+0

en utilisant une autre méthode (instrumentation JVM, hooks de débogage, AOP, etc)? – dfa

1

Comme d'autres l'ont dit ... S'il est une chose unique JVMTI est probablement la la façon la plus hardcore d'aller. Cependant, tout aussi amusant pourrait être d'utiliser la bibliothèque asm et les API d'instrumentation pour créer un agent qui insère un appel à une méthode statique que vous avez créée juste avant l'appel de Thread.interrupt() (ou peut-être modifie le Thread.interrupt () pour faire de même, je pense que vous pouvez le faire).

Les deux prend du temps à apprendre, mais il est très amusant de travailler avec et une fois que vous obtenez le feu, vous pouvez les utiliser pour toutes sortes de choses amusantes dans le futur :-) Je n'en ai pas vraiment bons extraits à coller ici maintenant, mais si vous google autour de ASM et peut-être regarder le JIP pour une utilisation créative de l'ASM, je pense que vous trouverez l'inspiration.

JIP: Java Interactive Profiler

+0

Je suppose que vous faites référence à http://asm.ow2.org/? Cela semble très créatif! Je n'ai pas eu le temps d'enquêter, mais cela ressemble à quelque chose qui me fera du bien à l'avenir. Merci. – Eddie

+0

Correct, désolé de ne pas inclure l'URL. – Fredrik

Questions connexes