2011-05-06 11 views

Respuesta

3

Para la mayoría de las JVM, todos los objetos se crean en el montón y Exception no es una excepción. ;)

Una JVM podría asignar objetos en la pila mediante el análisis de escape, sin embargo, esto generalmente se limita a los objetos que se usan solo en un método y no se devuelven. es decir, es muy poco probable que Excepciones sea un buen candidato.


Algo que es especial acerca de la forma en Throwables (Excepción incluido) se crean en muchas máquinas virtuales de Java es que los elementos traza de pila no se crean hasta que se necesiten. Esto se debe a que la mayoría de las veces no son necesarios y son caros de crear. Sin embargo, la información para crear el seguimiento de la pila se conserva en algún lugar por la JVM y se asocia con el Throwable, pero no es visible para el depurador o la reflexión.

public static void main(String... args) { 
    Throwable t = new Throwable("here"); 
    System.out.println("Throwable before getStackTrace()"); 
    shallowDump(t); 

    System.out.println("\nThrowable after getStackTrace()"); 
    t.getStackTrace(); 
    shallowDump(t); 
} 

private static void shallowDump(Object pojo) { 
    for (Field f : pojo.getClass().getDeclaredFields()) { 
     if (Modifier.isStatic(f.getModifiers())) continue; 
     f.setAccessible(true); 
     Object o; 
     try { 
      o = f.get(pojo); 
      if (o == pojo) 
       o = "{self}"; 
      if (o instanceof Object[]) 
       o = "Array of "+(o.getClass().getComponentType()); 
     } catch (Exception e) { 
      o = e; 
     } 
     System.out.println(f.getName() + ": " + o); 
    } 
} 

impresiones

Throwable before getStackTrace() 
detailMessage: here 
cause: {self} 
stackTrace: null 

Throwable after getStackTrace() 
detailMessage: here 
cause: {self} 
stackTrace: Array of class java.lang.StackTraceElement 

Entonces surge la pregunta, ¿dónde está la información que se usa para crear el StackTraceElement retenido. Al mirar el código, se usan métodos nativos para acceder a la información. Hay un campo misterioso llamado backtrace que no se puede ver con la reflexión.

System.gc(); 
for (int i = 0; i < 5; i++) { 
    Throwable[] ts = new Throwable[10000]; 
    long free = Runtime.getRuntime().freeMemory(); 
    for (int j = 0; j < ts.length; j++) 
     ts[j] = new Throwable(); 
    long used = free - Runtime.getRuntime().freeMemory(); 
    System.out.printf("Average Throwable size was %,d%n", used/ts.length); 
} 
System.gc(); 
for (int i = 0; i < 5; i++) { 
    Throwable[] ts = new Throwable[10000]; 
    long free = Runtime.getRuntime().freeMemory(); 
    for (int j = 0; j < ts.length; j++) 
     ts[j] = Throwable.class.newInstance(); 
    long used = free - Runtime.getRuntime().freeMemory(); 
    System.out.printf("Average Throwable.class.newInstance() size was %,d%n", used/ts.length); 
} 

Esto consigue el tamaño de un Throwable creado en el método actual y un Throwable creado en un método más profundo a través de la reflexión (que tiene una pila más profunda)

Average Throwable size was 302 
Average Throwable size was 302 
Average Throwable size was 302 
Average Throwable size was 302 
Average Throwable size was 302 
Average Throwable.class.newInstance() size was 247 
Average Throwable.class.newInstance() size was 296 
Average Throwable.class.newInstance() size was 296 
Average Throwable.class.newInstance() size was 296 
Average Throwable.class.newInstance() size was 296 

El tamaño de un Throwable es mucho más grande de lo que cabría esperar de los campos que tiene. Se puede suponer que parte de la información adicional se almacena en el montón para ayudar a esta clase, sin embargo, si toda la información se almacena en el objeto Throwable, se espera que el segundo tipo de Throwable sea más grande.

+1

Si una JVM desea cumplir con la especificación de VM, no puede crear objetos en la pila. La pila solo puede contener referencias. Ver 3.6.1 del JVMS: http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html # 15722 – musiKk

+1

@musiKk, acepto que el compilador no puede asignar objetos en la pila virtual para la máquina virtual. Sin embargo, lo que JVM hace cuando compila en código nativo puede ser muy diferente. –

+0

Estaba pensando en el análisis de Escape también, pero dado que los campos de 'Throwable' también son objetos, probablemente no funcionaría. Ver mi respuesta – BoffinbraiN

0

Todos los objetos en Java se asignan de forma predeterminada en un montón. Puede decir especialmente sobre las instancias de excepción, ya que comúnmente se pasan al método de la persona que llama, por lo que no es posible que estén en una pila.

0

Exception s (y todos Throwable s) son como cualquier otro tipo de objeto Java. Por lo tanto, aparecerán en el montón. Como señaló MusiKk, la pila solo puede contener valores primitivos o referencias a objetos.

+0

Los objetos están siempre en el montón. Solo las referencias pueden estar en la pila. – musiKk

+0

En 99.9% de los casos, sí ... * Sin embargo *, los últimos JDK pueden usar * Escape analysis * para determinar si una referencia al objeto alguna vez sale del alcance actual, y si no, no crea el objeto en absoluto, y pone los campos primitivos directamente en la pila si el espacio lo permite. Por otra parte, los campos de 'Throwable' también son objetos, así que tendrían que ir al montón de todas formas, así que supongo que no pensé en todo. Voy a editar eso. – BoffinbraiN

0

Se crean en el montón, pero ¿por qué es esto importante?

Cuestiones relacionadas