Estaba leyendo un libro sobre habilidades de programación en el que el autor le pregunta al entrevistado: "¿Cómo se bloquea una JVM?" Pensé que podría hacerlo escribiendo un bucle for infinito que eventualmente agotaría toda la memoria.
Alguien tiene alguna idea?
Respuestas:
Lo más parecido a una sola "respuesta" es
System.exit()
que termina la JVM inmediatamente sin una limpieza adecuada. Pero aparte de eso, el código nativo y el agotamiento de los recursos son las respuestas más probables. Alternativamente, puede buscar errores en el rastreador de errores de Sun en su versión de la JVM, algunos de los cuales permiten escenarios de fallas repetibles. Solíamos tener bloqueos semi-regulares cuando nos acercamos al límite de memoria de 4 Gb en las versiones de 32 bits (generalmente usamos 64 bits ahora).fuente
No llamaría lanzar un OutOfMemoryError o StackOverflowError como un bloqueo. Estas son solo excepciones normales. Para realmente bloquear una VM, hay 3 formas:
Para el último método, tengo un breve ejemplo, que bloqueará muy bien una máquina virtual Sun Hotspot:
Esto conduce a un desbordamiento de pila en el GC, por lo que no obtendrá StackOverflowError sino un bloqueo real que incluye un archivo hs_err *.
fuente
java.lang.OutOfMemoryError: GC overhead limit exceeded
JNI . De hecho, con JNI, el bloqueo es el modo de operación predeterminado. Tienes que trabajar muy duro para que no se bloquee.
fuente
Utilizar este:
Esta clase debe estar en el classpath de arranque porque está usando un código de confianza, por lo que debe ejecutarse así:
fuente
Field f = Unsafe.class.getDeclaredField( "theUnsafe" ); f.setAccessible( true ); unsafe = (Unsafe) f.get( null );
funcionó muy bien para mí.Unsafe
es, por definición, "inseguro". Esto es un poco tramposo.getDeclaredField
truco en JDK 8u131 en Linux x64, incluida la producción dehs_err_pid*.log
aSIGSEGV
.Unsafe
no es una trampa. OP no está buscando una solución 'limpia' para un problema de programación. Necesita que el JVM se estrelle de la manera más fea posible. Hacer cosas nativas desagradables es lo que puede hacer que eso suceda, y es exactamente lo queUnsafe
hace.Vine aquí porque también me encontré con esta pregunta en The Passionate Programmer , de Chad Fowler. Para aquellos que no tienen acceso a una copia, la pregunta se enmarca como una especie de filtro / prueba para los candidatos que se entrevistan para un puesto que requiere "realmente buenos programadores de Java".
Específicamente, él pregunta:
He programado en Java durante más de 15 años, y esta pregunta me pareció desconcertante e injusta. Como otros han señalado, Java, como lenguaje administrado, está específicamente diseñado para no bloquearse . Por supuesto, siempre hay errores de JVM, pero:
Como otros han mencionado, algunos códigos nativos a través de JNI son una forma segura de bloquear un JRE. Pero el autor mencionó específicamente en Java puro , así que eso está fuera.
Otra opción sería alimentar los códigos de bytes falsos de JRE; es bastante fácil volcar algunos datos binarios basura en un archivo .class y pedirle al JRE que lo ejecute:
¿Eso cuenta? Quiero decir que el JRE en sí no se ha estrellado; detectó correctamente el código falso, lo informó y salió.
Esto nos deja con los tipos más obvios de soluciones, como volar la pila a través de la recursión, quedarse sin memoria de almacenamiento dinámico a través de asignaciones de objetos o simplemente lanzar
RuntimeException
. Pero esto solo hace que el JRE salga con unaStackOverflowError
excepción o similar, que, de nuevo, no es realmente un bloqueo .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í .
PD: es un gran libro. Lo recogí como apoyo moral mientras aprendía Ruby.
fuente
Este código bloqueará la JVM de maneras desagradables
fuente
InternalError
JDK 1.8. JVM ya no falla.La última vez que intenté esto lo haría:
Primera parte del archivo de registro generado:
fuente
Una implementación perfecta de JVM nunca se bloqueará.
Para bloquear un JVM, aparte de JNI, debe encontrar un error en la propia máquina virtual. Un bucle infinito solo consume CPU. La asignación infinita de memoria solo debería causar OutOfMemoryError en una JVM bien construida. Esto probablemente causaría problemas para otros subprocesos, pero una buena JVM aún no debería fallar.
Si puede encontrar un error en el código fuente de la máquina virtual y, por ejemplo, causa un error de segmentación en el uso de la memoria de la implementación de la máquina virtual, puede bloquearlo.
fuente
Si desea bloquear JVM, utilice lo siguiente en Sun JDK 1.6_23 o inferior:
Esto se debe a un error en Sun JDK, que también se encuentra en OpenJDK. Esto se corrige desde Oracle JDK 1.6_24 en adelante.
fuente
Depende de lo que entiendas por choque.
Puedes hacer una recursión infinita para que se quede sin espacio de pila, pero eso se bloqueará "con gracia". Obtendrá una excepción, pero la propia JVM se encargará de todo.
También puede usar JNI para llamar a código nativo. Si no lo hace bien, puede hacer que se bloquee duro. La depuración de esos bloqueos es "divertida" (confía en mí, tuve que escribir una gran DLL de C ++ que llamamos desde un applet de Java firmado). :)
fuente
El libro Java Virtual Machine de Jon Meyer tiene un ejemplo de una serie de instrucciones de código de bytes que causaron que la JVM volcara el núcleo. No puedo encontrar mi copia de este libro. Si alguien tiene uno, búsquelo y publique la respuesta.
fuente
en winxpsp2 con wmp10 jre6.0_7
Desktop.open (uriToAviOrMpgFile)
Esto hace que un hilo generado arroje un Throwable no capturado y se bloquea el punto de acceso
YMMV
fuente
El hardware roto puede bloquear cualquier programa. Una vez tuve un bloqueo de la aplicación reproducible en una máquina específica mientras funcionaba bien en otras máquinas con exactamente la misma configuración. Resulta que la máquina tenía RAM defectuosa.
fuente
forma más corta posible :)
fuente
Exception in thread "main" java.lang.StackOverflowError at Test.main
. Estoy usando jdk1.8.0_65No es un choque, pero está más cerca de un choque que la respuesta aceptada de usar
System.exit
Puede detener la JVM llamando
Runtime.getRuntime().halt( status )
Según los documentos: -
fuente
Aquí hay una explicación detallada sobre lo que hace que JVM se descargue (es decir, se bloquee): http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_17534
fuente
Si quieres fingir que te has quedado sin memoria puedes hacerlo
Conozco un par de maneras de hacer que la JVM voltee un archivo de error llamando a métodos nativos (los que están integrados), pero probablemente sea mejor que no sepa cómo hacerlo. ;)
fuente
Si define un bloqueo como un proceso de aborto debido a una situación no controlada (es decir, sin excepción o error de Java), esto no se puede hacer desde Java (a menos que tenga permiso para usar la clase sun.misc.Unsafe). Este es todo el punto del código administrado.
Los bloqueos típicos en el código nativo ocurren al desreferenciar los punteros a áreas de memoria incorrectas (dirección nula o desalineada). Otra fuente podría ser instrucciones de máquina ilegales (códigos de operación) o señales no manejadas de la biblioteca o llamadas del núcleo. Ambos pueden activarse si la JVM o las bibliotecas del sistema tienen errores.
Por ejemplo, el código JITed (generado), los métodos nativos o las llamadas al sistema (controlador de gráficos) pueden tener problemas que conducen a bloqueos reales (era bastante común que se bloqueara cuando usaba funciones ZIP y se quedaban sin memoria). En esos casos, el controlador de fallas de la JVM entra y deja el estado. También podría generar un archivo de núcleo del sistema operativo (Dr. Watson en Windows y volcado de núcleo en * nix).
En Linux / Unix, puede realizar fácilmente un bloqueo de JVM enviándole una señal al proceso en ejecución. Nota: no debe usar
SIGSEGV
para esto, ya que Hotspot capta esta señal y la vuelve a lanzar como una NullPointerException en la mayoría de los lugares. Por lo tanto, es mejor enviar unSIGBUS
por ejemplo.fuente
JNI es una gran fuente de accidentes. También puede bloquearse usando la interfaz JVMTI ya que eso también debe escribirse en C / C ++.
fuente
Si crea un proceso de subproceso que genera infinitamente más subprocesos (que generan más subprocesos, que ...) eventualmente causará un error de desbordamiento de pila en la propia JVM.
Esto me dio la salida (después de 5 minutos, mira tu ram)
fuente
Si por "bloqueo" se refiere a un aborto abrupto de la JVM, como si la JVM escribiera en su hs_err_pid% p.log , puede hacerlo de esta manera.
Establezca el argumento Xmx en un valor pequeño y dígale a la JVM que fuerce un bloqueo en memoria:
Para ser claros, sin el segundo argumento anterior, solo resultaría en la terminación de jvm con un OutOfMemoryError, pero no se "bloqueará" o anulará abruptamente la jvm.
Esta técnica demostró ser útil cuando intentaba probar el argumento JVM -XX: ErrorFile, que controla dónde se debe escribir un registro de hs_err_pid. Encontré esta publicación aquí, mientras trataba de encontrar formas de forzar tal caída. Cuando más tarde descubrí que lo anterior funcionaba como lo más fácil para mi necesidad, quería agregarlo a la lista aquí.
Finalmente, FWIW, si alguien puede probar esto cuando ya tiene un valor -Xms establecido en sus argumentos (a un valor mayor que el anterior), también querrá eliminarlo o cambiarlo, o no obtendrá un bloqueo, sino simplemente un error de jvm para iniciar, informando "Tamaño de almacenamiento dinámico inicial establecido en un valor mayor que el tamaño de almacenamiento dinámico máximo". (Eso no sería obvio si ejecutara la JVM como servicio, como con algunos servidores de aplicaciones. Nuevamente, me mordió, así que quería compartirlo).
fuente
Si cambia ese bucle for infinito a una llamada recursiva a la misma función, obtendrá una excepción de desbordamiento de pila:
fuente
Lo estoy haciendo ahora, pero no estoy completamente seguro de cómo ... :-) JVM (y mi aplicación) a veces simplemente desaparecen por completo. No se arrojan errores, no se registra nada. Pasa de trabajar a no ejecutarse instantáneamente sin previo aviso.
fuente
Más corto? Use la clase Robot para activar CTRL + BREAK. Encontré esto cuando intentaba cerrar mi programa sin cerrar la consola (no tenía funcionalidad de 'salida').
fuente
¿Esto cuenta?
Solo funciona para Linux y desde Java 9.
Por alguna razón no entiendo,
ProcessHandle.current().destroyForcibly();
no mata la JVM y tirajava.lang.IllegalStateException
con el mensaje destruir del proceso actual no permitido .fuente
Se encuentra con este problema al intentar replicar el bloqueo de JVM.
Jni funciona, pero necesita ser ajustado para diferentes plataformas. Finalmente, uso esta combinación para hacer que JVM se bloquee
-XX:+CrashOnOutOfMemoryError
long[] l = new long[Integer.MAX_VALUE];
para activar el OOMEntonces JVM se bloqueará y generará el registro de bloqueo.
fuente
Si un 'Crash' es algo que interrumpe el programa jvm / de la terminación normal, entonces una excepción no manejada podría hacer esto.
Entonces, ¿depende de qué tipo de CRASH?
fuente
ArithmeticException
son