Pregunta

Yo estaba leyendo un libro sobre las habilidades de programación en el que el autor pide al entrevistado, "Cómo hacer que choque con una JVM?" Pensé que podría hacerlo escribiendo un infinito de bucle que podría, eventualmente, el uso de toda la memoria.

Alguien tiene alguna idea?

¿Fue útil?

Solución

La cosa más cercana a una sola "respuesta" es System.exit() lo que termina la JVM inmediatamente sin una limpieza adecuada.Pero aparte de eso, el código nativo y el agotamiento del recurso son los más probables respuestas.Alternativamente, usted puede ir a buscar en el Sol de del bug tracker para fallos en su versión de la JVM, algunos de los cuales permiten repetible escenarios de caída.Se utilizó para obtener semi-regulares se bloquea cuando se aproxima la memoria de 4 Gb límite en las versiones de 32 bits (en general, el uso de 64 bits ahora).

Otros consejos

Yo no llamaría a lanzar un OutOfMemoryError o StackOverflowError un accidente.Estos son sólo excepciones normales.Realmente el bloqueo de un VM hay 3 maneras:

  1. El uso de JNI y se colgará en el código nativo.
  2. Si no hay seguridad de que está instalado el administrador puede utilizar la reflexión a la caída de la VM.Este es VM específico, pero normalmente una VM tiendas un montón de punteros a los nativos de los recursos en campos privados (por ejemplo,un puntero al hilo nativo objeto se almacena en un campo largo en java.lang.Hilo).Acaba de cambiar a ellos a través de la reflexión y la VM se caerá tarde o temprano.
  3. Todas las máquinas virtuales tienen errores, por lo que sólo tiene que activar uno.

Para el último método que tenemos un breve ejemplo, que va a provocar la caída de un Sol Hotspot VM tranquila muy bien:

public class Crash {
    public static void main(String[] args) {
        Object[] o = null;

        while (true) {
            o = new Object[] {o};
        }
    }
}

Esto conduce a un desbordamiento de pila en el GC por lo que se obtiene no StackOverflowError pero una caída real incluyendo un hs_err* archivo.

JNI.De hecho, con JNI, rompiendo es el modo predeterminado de operación.Usted tiene que trabajar más duro para conseguir que no se bloquee.

El uso de este:

import sun.misc.Unsafe;

public class Crash {
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    public static void crash() {
        unsafe.putAddress(0, 0);
    }
    public static void main(String[] args) {
        crash();
    }
}

Esta clase debe estar en el arranque classpath porque está utilizando el código de confianza,por lo que funcionan como esto:

java -Xbootclasspath/p:.Crash

Vine aquí porque yo también corrió a esta pregunta en El Programador Apasionado, por Chad Fowler.Para aquellos que no tienen acceso a una copia, la pregunta se enmarca como una especie de filtro/prueba para entrevistar a los candidatos para un puesto que requiere "realmente bueno que los programadores de Java."

En concreto, se pide:

¿Cómo se escribe un programa en Java puro, que podrían provocar que la Máquina Virtual de Java para crash?

He programado en Java por más de 15 años, y me encontré con esta pregunta para ser a la vez desconcertante y desleal.Como otros han señalado, Java, como lenguaje administrado, está diseñado específicamente de no chocar.Por supuesto siempre hay JVM errores, pero:

  1. Después de más de 15 años de producción a nivel de JREs, es raro.
  2. Cualquiera de dichos errores son probables ser parcheado en la próxima versión, así que ¿qué probabilidad hay de que como un programador para correr y recordar los detalles de la configuración actual de JRE show-tapones?

Como otros han mencionado, algunos nativos de código a través de JNI es una manera segura de provocar la caída de un JRE.Pero el autor menciona específicamente en Java puro, por lo que está fuera.

Otra opción sería la de alimentar el JRE falsos códigos de byte;es bastante fácil para el volcado de algunas de basura datos binarios a un .archivo de clase, y pedir el JRE para ejecutarlo:

$ echo 'crap crap crap' > crap.class
$ java crap
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1668440432 in class file crap

¿Que cuentan?Me refiero a la versión de JRE en sí no ha estrellado;se detecta correctamente el falso código, informó, y salió.

Esto nos deja con la más obvia tipo de soluciones, tales como el soplado de la pila a través de la recursividad, corriendo de memoria de pila a través de las colocaciones de objetos, o simplemente tirar RuntimeException.Pero esto sólo hace que el JRE para salir con un StackOverflowError o similares de excepción, que, de nuevo no es realmente un accidente.

Entonces, ¿qué queda?Realmente me encantaría escuchar lo que el autor realmente tenía en mente como una solución adecuada.

Actualización:Chad Fowler respondió aquí.

PS:es un gran libro.Lo cogí por el apoyo moral, mientras que el aprendizaje de Rubí.

Este código se bloqueará la JVM en desagradable maneras

import sun.dc.pr.PathDasher; 

public class Crash
{
     public static void main(String[] args)
     {    
        PathDasher dasher = new PathDasher(null) ;
     }
}

La última vez que probé este haría:

public class Recur {
    public static void main(String[] argv) {
        try {
            recur();
        }
        catch (Error e) {
            System.out.println(e.toString());
        }
        System.out.println("Ended normally");
    }
    static void recur() {
        Object[] o = null;
        try {
            while(true) {
                Object[] newO = new Object[1];
                newO[0] = o;
                o = newO;
            }
        }
        finally {
            recur();
        }
    }
}

Primera parte del archivo de registro generado:

#
# An unexpected error has been detected by Java Runtime Environment:
#
#  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x000000006dad5c3d, pid=6752, tid=1996
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.2-b01 mixed mode windows-amd64)
# Problematic frame:
# V  [jvm.dll+0x2e5c3d]
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

---------------  T H R E A D  ---------------

Current thread (0x00000000014c6000):  VMThread [stack: 0x0000000049810000,0x0000000049910000] [id=1996]

siginfo: ExceptionCode=0xc00000fd, ExceptionInformation=0x0000000000000001 0x0000000049813fe8 

Registers:
EAX=0x000000006dc83090, EBX=0x000000003680f400, ECX=0x0000000005d40ce8, EDX=0x000000003680f400
ESP=0x0000000049813ff0, EBP=0x00000000013f2df0, ESI=0x00000000013f0e40, EDI=0x000000003680f400
EIP=0x000000006dad5c3d, EFLAGS=0x0000000000010206

Una perfecta implementación de la JVM nunca choque.

Bloquee una JVM, aparte de la JNI, usted necesita encontrar un error en la máquina virtual de la misma.Un bucle infinito sólo consume CPU.Infinitamente asignación de memoria sólo debe causar OutOfMemoryError en un pozo construido en la JVM.Esto probablemente podría causar problemas a otros hilos, pero un buen JVM todavía no debe bloquearse.

Si usted puede encontrar un error en el código fuente de la máquina virtual, y, por ejemplo, provocar un fallo de segmentación en el uso de la memoria de la implementación de la máquina virtual, entonces usted puede crash.

Si desea accidente JVM - utilice la siguiente en Sun JDK 1.6_23 o a continuación:

Double.parseDouble("2.2250738585072012e-308");

Esto es debido a un error en Sun JDK - también se encuentra en OpenJDK.Este se fija a partir de Oracle JDK 1.6_24 en adelante.

Depende de a qué te refieres por accidente.

Usted puede hacer una recursividad infinita para hacer que se ejecute fuera de espacio en la pila, pero que va a chocar "con gracia".Usted obtendrá una excepción, pero la JVM sí se puede controlar todo.

También puede utilizar JNI para llamar a código nativo.Si usted no hace lo que es correcto, entonces usted puede hacer accidente de disco duro.La depuración de los accidentes es "divertido" (confía en mí, yo tenía que escribir una gran DLL en C++ que nos llamada de un subprograma java).:)

El libro La Máquina Virtual De Java por Jon Meyer tiene un ejemplo de una serie de instrucciones de bytecode que causó la JVM de volcado del núcleo.No puedo encontrar mi copia de este libro.Si alguien tiene uno por favor buscar y publicar la respuesta.

en winxpsp2 w/wmp10 jre6.0_7

De escritorio.abierto(uriToAviOrMpgFile)

Esto hace generado un hilo para lanzar una uncaught Arrojadiza y se bloquea hotspot

YMMV

Hardware roto puede bloquear cualquier programa.Una vez tuve un bloqueo de la aplicación reproducably en una máquina específica mientras se ejecuta bien en otros equipos con la misma configuración.Resulta que la máquina había RAM defectuosa.

la forma más corta posible :)

public class Crash
{
    public static void main(String[] args)
    {
        main(args);
    }
}

No es un accidente, pero se acercan a un accidente que la aceptan respuesta de usar System.exit

Puedes detener la JVM llamando

Runtime.getRuntime().halt( status )

De acuerdo a la documentación :-

"este método no causa el cierre de los ganchos para ser iniciado y no se ejecuta uninvoked finalizadores si la finalización-en-salida ha sido habilitado".

aquí está una explicación detallada sobre las causas de la JVM de volcado de núcleo (es decir,crash):http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_17534

Si se define un accidente como un proceso de abortar a causa de una situación no controlada (es decir,no Java Excepción o Error), entonces esto no puede hacerse desde dentro de Java (a menos que tenga permiso para utilizar el sol.misc.Clase inseguro).Este el punto de código administrado.

Típico de los accidentes en el código nativo de pasar por de-referencia punteros a mal áreas de memoria (dirección nula o missaligned).Otra fuente podría ser ilegal instrucciones de la máquina (opcodes) o no controlada de las señales de la biblioteca o del núcleo de llamadas.Tanto puede ser activada si la JVM o el sistema de bibliotecas tiene errores.

Por ejemplo JITed (generado) código de los métodos nativos o de las llamadas del sistema (controlador de gráficos) puede tener problemas que conducen a la real se bloquea (era bastante común para obtener un accidente cuando se utiliza POSTAL de funciones y corrieron fuera de la memoria).En los casos en que el manejador de errores de la JVM patadas y vuelca el estado.También podría generar un OS del archivo central (Dr.Watson en Windows y volcado de núcleo en *nix).

En Linux/Unix puede easyly hacer una JVM de choque mediante el envío de una Señal al proceso de ejecución.Nota:usted no debe usar SIGSEGV para ello, desde el Hotspot de las capturas de esta señal y re-lanza como un NullPointerException en la mayoría de los lugares.Así que es mejor enviar un SIGBUS por ejemplo.

Si quieres fingir que se ha quedado sin memoria que usted puede hacer

public static void main(String[] args) {
    throw new OutOfmemoryError();
}

Yo conozco a un par de camino a causa de la JVM de volcado de un archivo de error llamando a los métodos nativos (los que están integrados en), pero probablemente es mejor que no saber cómo hacerlo.;)

JNI es una gran fuente de accidentes.También puede bloquearse mediante el JVMTI de la interfaz, ya que debe ser escrito en C/C++.

Si se crea un hilo de proceso que infinitamente genera más hilos (que genere más subprocesos, que...) que finalmente va a causar un error de desbordamiento de pila en la JVM sí mismo.

public class Crash {
    public static void main(String[] args) {

        Runnable[] arr = new Runnable[1];
        arr[0] = () -> {

            while (true) {
                new Thread(arr[0]).start();
            }
        };

        arr[0].run();
    }
}

Esto me dio la salida (después de 5 minutos, el reloj de la memoria ram)

An unrecoverable stack overflow has occurred.
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x0000000070e53ed7, pid=12840, tid=0x0000000000101078
#
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# 

Más corto?El uso de Robots de clase para activar CTRL+INTER.He visto esto cuando yo estaba tratando de cerrar mi programa sin cerrar la consola (no tenía la 'salida' de la funcionalidad).

Yo estoy haciendo ahora, pero no del todo seguro de cómo...:-) JVM (y mi app) a veces simplemente desaparecer por completo.No hay errores lanzado, nada conectado.Va desde el trabajo no se ejecuta en todo instante, sin previo aviso.

¿Este recuento ?

long pid = ProcessHandle.current().pid();
try { Runtime.getRuntime().exec("kill -9 "+pid); } catch (Exception e) {}

Sólo funciona para Linux y Java 9.

Por alguna razón, no lo entiendo, ProcessHandle.current().destroyForcibly(); no matar a la JVM y lanza java.lang.IllegalStateException con el mensaje destruir de proceso actual no permite.

Si tiene que cambiar ese infinito bucle for para una llamada recursiva a la misma función, entonces se puede obtener una excepción de desbordamiento de pila:

public static void main(String[] args) {
    causeStackOverflow();
}

public void causeStackOverflow() {
    causeStackOverflow();
}

Si un 'Crash' es algo que interrumpe la jvm/programa de terminación normal, luego de naciones unidas excepción controlada podría hacer esto.

public static void main(String args[]){
   int i = 1/0;
   System.out.print(i); // This part will not be executed due to above  unhandled exception
  }

Así que, depende de qué tipo de ACCIDENTE ?!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top