java - personalizar - ¿Se puede llamar a finalize después de que un constructor lanza una excepción?
mostrar excepciones java (3)
¿Hay detalles sobre si un objeto se limpia o no con finalize()
si el constructor de ese objeto es una excepción?
Cuando se llama a este método es notoriamente mal definido. Según el manual:
El lenguaje de programación Java no garantiza qué subproceso invocará el método de finalización para cualquier objeto dado. Sin embargo, se garantiza que el subproceso que invoca finalize no mantendrá ningún bloqueo de sincronización visible cuando se invoque finalize. Si el método finalize lanza una excepción no detectada, la excepción se ignora y la finalización de ese objeto termina.
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29
No he podido activar el método de finalización de esta manera. ¿Alguien sabe si se ha pedido que NO se llame o si en algunos casos se llama después de que el constructor no pudo inicializar el objeto (por ejemplo, una excepción).
Lo pregunto porque tengo un objeto que no se debe limpiar dos veces. Estoy tratando de entender si es seguro limpiar antes de lanzar la excepción o si debo dejar un marcador para finalize()
para omitir y no hacer nada de manera efectiva.
Mi prueba muestra que puede
public class Test1 {
Test1() {
throw new RuntimeException();
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalized");
}
public static void main(String[] args) throws Exception {
try {
new Test1();
} catch (RuntimeException e) {
e.printStackTrace();
}
System.gc();
Thread.sleep(1000);
}
}
huellas dactilares
java.lang.RuntimeException
at test.Test1.<init>(Test1.java:13)
at test.Test1.main(Test1.java:24)
finalized
está en Java HostSpot Client VM 1.7.0_03
Para demostrar más claramente:
public class Test1 {
public static class LifeBoat extends RuntimeException
{
private Test1 passenger;
public Test1 getPassenger(){return passenger;}
public LifeBoat(Test1 passenger){this.passenger=passenger;}
}
Test1() {
super(); //once this is finished, there is an Object to GC per JLS 12.6.1.
throw new LifeBoat(this);
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalized");
}
public static void main(String[] args) throws Exception {
try {
new Test1();
} catch (LifeBoat e) {
Test1 obj;
obj=e.getPassenger();
System.out.println(obj);
}
System.gc();
Thread.sleep(1000);
}
}
huellas dactilares
java.lang.RuntimeException
at test.Test1.<init>(Test1.java:13)
at test.Test1.main(Test1.java:24)
test.Test1@6dc8f3cd
finalized
Según la sección 12.6.1. Implementación de la finalización del JLS:
Un objeto o no se puede finalizar hasta que su constructor haya invocado el constructor para Objeto en o y esa invocación se haya completado con éxito (es decir, sin lanzar una excepción).
Si su constructor lanza una excepción después de que el constructor del objeto se completa, entonces su objeto debería ser finalizable, por lo que aún podría llamarse finalize()
.
Hay un buen ejemplo de paso a través de la construcción de objetos en la sección 12.5. Creación de nuevas instancias de clase que muestra exactamente cuándo se llama al constructor de objetos.