2012-09-06 12 views
9

Cómo puedo crear un volcado dinámico desde mi aplicación, sin utilizar la clase HotSpotDiagnosticMXBean. Debido a la restricción de acceso de java/rt.jar no puedo compilarlo con una dependencia a HotSpotDiagnosticMXBean. Sé cómo resolver el error de eclipse.compiler, pero ¿cómo puedo solucionarlo en mi compilación? ¿Existe alguna alternativa a la forma de crear un volcado de pila de forma programática?crear volcado dinámico desde la aplicación, sin HotSpotDiagnosticMXBean

+0

¿Has leído esto: http://java.sun.com/developer/technicalArticles/J2SE/monitoring/? –

+0

¿No puede levantar la restricción de acceso para que pueda hacerlo de la forma en que se supone que debe hacerlo? O necesita hacer esto y puede tener acceso o no, en cuyo caso no debe intentarlo. –

+0

@ Peter Lawrey no puedo levantar la restricción (¿tal vez haya una opción de compilación?) La segunda opción es activar un volcado de almacenamiento intermedio de otra manera. – Chriss

Respuesta

14

bien, parece que puede pasar por alto la restricción mediante el uso de la reflexión:

package lab.heapdump; 

import javax.management.MBeanServer; 
import java.lang.management.ManagementFactory; 
import java.lang.reflect.Method; 


@SuppressWarnings("restriction") 
public class HeapDump { 
    // This is the name of the HotSpot Diagnostic MBean 
    private static final String HOTSPOT_BEAN_NAME = 
     "com.sun.management:type=HotSpotDiagnostic"; 

    // field to store the hotspot diagnostic MBean 
    private static volatile Object hotspotMBean; 

    /** 
    * Call this method from your application whenever you 
    * want to dump the heap snapshot into a file. 
    * 
    * @param fileName name of the heap dump file 
    * @param live flag that tells whether to dump 
    *    only the live objects 
    */ 
    static void dumpHeap(String fileName, boolean live) { 
     // initialize hotspot diagnostic MBean 
     initHotspotMBean(); 
     try { 
      Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); 
      Method m = clazz.getMethod("dumpHeap", String.class, boolean.class); 
      m.invoke(hotspotMBean , fileName, live); 
     } catch (RuntimeException re) { 
      throw re; 
     } catch (Exception exp) { 
      throw new RuntimeException(exp); 
     } 
    } 

    // initialize the hotspot diagnostic MBean field 
    private static void initHotspotMBean() { 
     if (hotspotMBean == null) { 
      synchronized (HeapDump.class) { 
       if (hotspotMBean == null) { 
        hotspotMBean = getHotspotMBean(); 
       } 
      } 
     } 
    } 

    // get the hotspot diagnostic MBean from the 
    // platform MBean server 
    private static Object getHotspotMBean() { 
     try { 
      Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); 
      MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 
      Object bean = 
       ManagementFactory.newPlatformMXBeanProxy(server, 
       HOTSPOT_BEAN_NAME, clazz); 
      return bean; 
     } catch (RuntimeException re) { 
      throw re; 
     } catch (Exception exp) { 
      throw new RuntimeException(exp); 
     } 
    } 

    public static void main(String[] args) { 
     // default heap dump file name 
     String fileName = "D:\\heap.bin"; 
     // by default dump only the live objects 
     boolean live = true; 

     // simple command line options 
     switch (args.length) { 
      case 2: 
       live = args[1].equals("true"); 
      case 1: 
       fileName = args[0]; 
     } 

     // dump the heap 
     dumpHeap(fileName, live); 
    } 
} 
+0

¡La reflexión funciona! Uno solo tiene que verificar si la clase 'HotSpotDiagnosticMXBean' está disponible en el jdk actual. – Chriss

+0

Parece haber sido adaptado de https://blogs.oracle.com/sundararajan/entry/programmatically_dumping_heap_from_java –

+0

¿Estás seguro de que esto funcionará? Si escribo esto: getMethod ("dumpHeap", String.class, boolean.class) .. Recibo el error "no aplicable para los argumentos String, Class , Class " ... así que tengo que usar array: new Class [ ] {String.class, boolean.class} como el segundo parámetro y la invocación se hace así: m.invoke (hotspotMBean, new Object [] {fileName, Boolean.valueOf (live)}); – Racky

0

VisualVM puede hacer un volcado del montón.

También puede probar el comando jhat en sistemas Linux.

+1

Lo sé, pero quiero activar un heapdump desde mi aplicación, sin la necesidad de un programa externo. – Chriss

0

Esta clase es pública, por lo que es posible que no tenga acceso a ella porque no la tiene en su versión de JVM porque es demasiado antigua.

El ejemplo vinculado a compila y funciona bien en Java 6 y 7. Si es posible, intente actualizar a una versión reciente de Java.

+2

Estoy usando java7. El problema es que HotSpotDiagnosticMXBean no es una clase pública HotSpotDiagnosticMXBean (no es parte de jdk). Esta clase existe solo en la distribución de oráculo Java, depende de JVM. – Chriss

+0

Esto significa que la función depende de JVM y puede compilar el código, pero es posible que no se ejecute en JVM que no admitan esta característica. ¿Qué sabores de JVM estás usando? –

0

Puede copiar el rt.jar que tiene la HotSpotDiagnosticMXBean.class a una ubicación diferente. Consulte el archivo copiado en la ruta de compilación con "Agregar contenedor externo". Esto le permite crear Objeto y obtener el volcado de Heap.

new HotSpotDiagnostic().dumpHeap("d:\\HeapDump1",true); 

Pude generar Heapdump de esta manera. Estaba buscando cualquier error de conflicto de tiempo de ejecución. Afortunadamente ninguno.

Cuestiones relacionadas