2009-04-28 14 views
6

Me gustaría registrar de alguna manera cada vez que se llama Thread.interrupt(), registrando qué hilo emitió la llamada (y su pila actual), así como información de identificación sobre qué subproceso se está interrumpiendo.¿Hay alguna forma en Java para registrar * cada * interrupción de subprocesos?

¿Hay alguna manera de hacerlo? Buscando información, vi que alguien hizo referencia a la posibilidad de implementar un administrador de seguridad. ¿Es esto algo que se puede hacer en tiempo de ejecución (por ejemplo, en un Applet o cliente de Web Start), o necesita herramienta de la JVM instalada para hacer esto?

¿O hay una manera mejor de hacer esto?

+0

Puedo pensar en algunas formas de hacerlo con diferente complejidad y diferentes éxitos de rendimiento. ¿Es una sola vez encontrar un error o es algo que desea en producción? – Fredrik

+0

Esto es principalmente algo que quiero como algo que ocurre una sola vez, pero es algo que sé que querré usar de vez en cuando. Si fuera lo suficientemente amigable, lo dejaría en el código de producción, pero se desactivaría como un modo adicional de depuración remota (a través de registros) para usarlo cuando sea necesario. – Eddie

Respuesta

9

Como un corte rápido, éste era muchomás fácil de hacer de lo que pensaba que sería. Dado que este es un corte rápido, no lo hice cosas como asegurarse de que el seguimiento de la pila es lo suficientemente profunda antes de eliminación de referencias a la matriz, etc. insertar el siguiente en mi firmado el constructor del 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); 
     } 
    }); 

y el método dumpThreadStack es el siguiente:

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

nunca podría, por supuesto, dejar esto en el código de producción, pero fue suficiente para decirme exactamente por cuál de ellos estaba causando un interrupt() que no esperaba. Es decir, con este código en su lugar, obtengo un volcado de pila para cada llamada al Thread.interrupt().

+1

Tenga en cuenta que en algunas versiones de Java el SecurityManager también debe anular los métodos checkPermission (para la opción más permisiva y simple, pídales que simplemente devuelvan) o de lo contrario puede golpear los errores de seguridad como 'java.security.AccessControlException: access denied'. – vazor

4

Antes de intentar algo demasiado salvaje, ¿ha considerado usar el Java debuggingAPI? Creo que capturar MethodEntryEvents en Thread.interrupt() lo haría.

Eeek, esa es la interfaz anterior, también debe consultar la nueva JVM ToolInterface.

+0

Soy vagamente consciente de la API de depuración de Java, pero no estoy seguro de cómo usarla desde la aplicación en la que la usaría. – Eddie

+0

Te he dado un par de enlaces ahora; la respuesta corta es que agrega un indicador a la invocación JVM y luego puede conectarse a la JVM externamente. –

+0

Lamentablemente, sus sugerencias no me ayudarán. La nueva interfaz de la herramienta JVM requiere JNI y la antigua API de depuración de Java no está disponible para Applets. Sin embargo, esta información puede ser útil para otra cosa en el futuro. Gracias por los consejos. – Eddie

2

Me gustaría ver AspectJ y sus capacidades para envolver llamadas a métodos. Un execution pointcut alrededor del método interrupt() debería ayudar aquí.

Tenga en cuenta que, dado que está buscando interceptar una llamada al método del sistema Java (a diferencia de su código de aplicación), el anterior puede no ser adecuado. This thread parece sugerir que es posible, pero tenga en cuenta que ha creado tejido rt.jar.

+0

. ¿Puede incluso envolver métodos en las bibliotecas de JVM? – Eddie

+0

Ese es un buen punto, y uno que estaba considerando justo cuando lo escribí. Hay varios mecanismos diferentes de tejido de bytes, sin duda (tiempo de compilación/tiempo de ejecución/tiempo de carga de clases), por lo que uno de estos puede funcionar. –

0

Usted podría tratar también con JMX:

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID) 

con el objeto ThreadInfo puede iniciar sesión:

  • el seguimiento de pila de la rosca
  • información general Userful como nombre, estado, etc.
  • etc

EDIT

getAllThreadIds uso() con el fin de obtener la lista de identificadores de hilo directo:

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

¿Cómo quieres decir que atraparía la llamada de interrupción? – Fredrik

+0

usando otro método (instrumentación JVM, anzuelos de depuración, AOP, etc.)? – dfa

1

Como otros han dicho ... Si se trata de una cosa de una sola vez es probablemente la JVMTI La forma más difícil de ir. Sin embargo, igual de divertido podría ser utilizar la biblioteca asm y las API de instrumentación para crear un agente que inserte una llamada a un método estático que haya creado justo antes de la llamada Thread.interrupt() (o tal vez altere la interrupción.del hilo) () método para hacer lo mismo, creo que puedes hacer eso).

Ambos tardan un tiempo en aprender, pero es muy divertido trabajar con él y una vez que lo tienes puedes utilizarlo para todo tipo de cosas divertidas en el futuro :-) Realmente no tengo ninguna buenos fragmentos para pegar aquí ahora, pero si buscas en Google ASM y tal vez consultes el JIP para un uso creativo de ASM, creo que encontrarás inspiración.

JIP Java Interactive Profiler

+0

Supongo que te estás refiriendo a http://asm.ow2.org/? ¡Suena muy creativo! No tuve tiempo para investigar, pero esto parece algo que me hará bien en el futuro. Gracias. – Eddie

+0

Correcto, disculpe por no incluir la URL. – Fredrik

Cuestiones relacionadas