Pergunta

Eu estava lendo um livro sobre habilidades de programação na qual o autor pede que o entrevistado, "Como você se falhar uma JVM?" Eu pensei que você poderia fazer isso por escrito de um infinito ciclo que iria, eventualmente, utilizar toda a memória.

Alguém tem alguma idéia?

Foi útil?

Solução

A coisa mais próxima de uma única "resposta" é System.exit() o que termina a JVM imediatamente, sem a limpeza adequada.Mas, para além de que, o código nativo e o esgotamento de recursos são os mais prováveis respostas.Alternativamente, você pode ir olhando no Sol bug tracker para bugs na versão da JVM, alguns dos quais permitem repetitivo possíveis cenários de crise.Foi utilizado para receber semi-regulares falha quando se aproxima a 4 Gb de memória prazo, de acordo com as versões de 32 bits (geralmente usamos 64 bits agora).

Outras dicas

Eu não chamaria jogando um OutOfMemoryError ou StackOverflowError um acidente.Estes são apenas normais exceções.Realmente, a queda de uma VM existem 3 maneiras:

  1. Usar JNI e falha em código nativo.
  2. Se nenhum gestor de segurança é instalado, você pode usar a reflexão para a falha do VM.Este é o VM específico, mas normalmente uma VM armazena um monte de ponteiros para recursos nativos em campos particulares (e.g.um ponteiro para a thread nativa objeto é armazenado em um longo campo no o java.lang.Thread).Basta alterá-las através de reflexão e a VM irá falhar mais cedo ou mais tarde.
  3. Todas as VMs ter bugs, então você apenas tem que acionar um.

Para o último método de eu ter um pequeno exemplo, que irá falhar uma Sun Hotspot VM tranquila, muito bem:

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

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

Isso leva a uma sobrecarga de pilha no GC, então você vai ficar sem StackOverflowError, mas uma real queda incluindo um hs_err* arquivo.

JNI.Na verdade, com JNI, bater é o modo padrão de operação.Você tem que trabalhar duro extra para obtê-lo para não cair.

Use isto:

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 classe deve estar no arranque classpath porque ele está usando o código de confiança,de modo a executar assim:

java -Xbootclasspath/p:.Acidente

Eu vim aqui porque eu também correram para esta pergunta O Programador Apaixonado, Chad Fowler.Para aqueles que não têm acesso a uma cópia, a pergunta é formulada como uma espécie de filtro/teste para os candidatos de entrevistas para uma posição de exigir "muito bom programadores de Java."

Especificamente, ele pergunta:

Como é que você escreve um programa, em Java puro, que faria com que a Máquina Virtual de Java para falhar?

Eu já programados em Java há mais de 15 anos, e eu encontrei essa pergunta a ser intrigante e injusto.Como outros já apontaram, Java, uma linguagem gerenciada, é projetado especificamente para não falhar.É claro que há sempre a JVM bugs, mas:

  1. Depois de+ de 15 anos de produção-nível de JREs, é raro.
  2. Tais erros são susceptíveis de ser corrigido na próxima versão, assim como a probabilidade de você como um programador para executar e recuperar os detalhes do conjunto atual de JRE mostrar-rolhas?

Como outros já mencionados, alguns de código nativo via JNI é uma maneira de bater o JRE.Mas o autor mencionado especificamente em Java puro, de modo que está fora.

Outra opção seria a de alimentar o JRE falsos códigos de byte;é fácil o suficiente para despejar algum lixo dados binários para um .arquivo de classe, e pede para o JRE para executá-lo:

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

Faz essa contagem?Eu quero dizer o JRE em si ainda não caiu;é correctamente detectado o falso código, relatou ele, e saiu.

Isto deixa-nos com a mais óbvia tipos de soluções, tais como soprando a pilha através de recursão, executando fora do heap de memória através de alocações de objetos, ou simplesmente jogando RuntimeException.Mas isso só faz com que o JRE para sair com um StackOverflowError ou similar exceção, o que, novamente não é realmente uma falha.

Então, o que sobra?Eu adoraria ouvir o que o autor realmente tinha em mente como uma solução adequada.

Atualização:Chad Fowler respondeu aqui.

PS:é um grande livro.Peguei-a para dar apoio moral ao aprender Ruby.

Este código irá falhar a JVM na desagradável formas

import sun.dc.pr.PathDasher; 

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

A última vez que eu tentei isso iria fazê-lo:

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();
        }
    }
}

Primeira parte do arquivo de log gerado:

#
# 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

Uma perfeita implementação da JVM nunca vai falhar.

A falha de uma JVM, além da JNI, você precisa encontrar um bug em uma VM em si.Um loop infinito apenas consome CPU.Infinitamente alocação de memória deve justa causa OutOfMemoryError em uma bem construída JVM.Essa seria, provavelmente, causar problemas para outros segmentos, mas um bom JVM ainda não deve falhar.

Se você pode encontrar um erro no código-fonte da VM, e, por exemplo, causa uma falha de segmentação no uso de memória da aplicação da VM, em seguida, você pode realmente funcionar.

Se você quer falhar JVM - o uso da Sun JDK 1.6_23 ou abaixo:

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

Isto é devido a um erro em Sun JDK - também encontrado no OpenJDK.Isso é corrigido a partir do Oracle JDK 1.6_24 em diante.

Depende do que você entende por acidente.

Você pode fazer uma recursão infinita para que ele seja executado fora do espaço de pilha, mas que vou falhar "graciosamente".Você vai receber uma exceção, mas a JVM em si vai estar lidando com tudo.

Você também pode usar JNI para chamar código nativo.Se você não fazê-lo apenas para a direita, em seguida, você pode fazê-lo falhar rígido.Depuração essas falhas é "divertido" (confie em mim, eu tinha que escrever um grande C++ DLL que podemos chamar de um applet de java assinado).:)

O livro Java Virtual Machine por Jon Meyer tem um exemplo de uma série de instruções de bytecode que causou a JVM para o despejo.Eu não consigo encontrar a minha cópia do livro.Se alguém aí tem um, por favor, procure postar a resposta.

no winxpsp2 w/wmp10 jre6.0_7

Área de trabalho.abrir(uriToAviOrMpgFile)

Isso faz com que um thread de expansão para lançar uma não identificada Throwable e falha hotspot

YMMV

Quebrado de hardware pode falhar a qualquer programa.Uma vez eu tive um aplicativo falhar reproducably em uma máquina específica durante a execução de multa em outras máquinas com a mesma configuração.Acontece que a máquina tinha RAM com defeito.

menor maneira possível :)

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

Não é um acidente, mas mais um acidente do que o aceite resposta de usar System.exit

Você pode interromper a JVM chamando

Runtime.getRuntime().halt( status )

De acordo com o google docs :-

"esse método não causa desligamento ganchos para ser iniciado e não executar uninvoked finalizadores se a finalização na saída tem sido habilitado".

aqui está uma explicação detalhada sobre o que faz com que a JVM para o core dump (i.e.crash):http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_17534

Se você definir uma falha como um processo abortar devido a uma não tratada situação (i.e.nenhum Java Exceção ou Erro), então isso não pode ser feito dentro do Java (a menos que você tenha permissão para usar o sol.diversos.Classe inseguro).Este o ponto de código gerenciado.

Típico de falha em código nativo acontecer de referência de ponteiros para errado áreas de memória (endereço nulo ou missaligned).Outra fonte poderia ser ilegal instruções de máquina (opcodes) ou sem tratamento de sinais a partir da biblioteca de kernel ou de chamadas.Tanto pode ser acionada se a JVM ou o sistema de bibliotecas tem bugs.

Por exemplo JITed (gerado) de código, métodos nativos ou chamadas de sistema (graphics driver) pode ter problemas, levando a real falha (era muito comum para obter uma falha quando você usar o ZIP funções e eles correram para fora da memória).Nesses casos, a falha manipulador da JVM chutes e despeja o estado.Ele também pode gerar um sistema operacional de núcleo de arquivo (Dr.Watson no Windows e o despejo em *nix).

No Linux/Unix você pode easyly fazer uma falha JVM, enviando um Sinal para o processo de execução.Nota:você não deve usar SIGSEGV para isso, desde Hotspot identificou este sinal e re-lança-lo como um NullPointerException na maioria dos lugares.Por isso, é melhor enviar um SIGBUS por exemplo.

Se você quiser fingir que você tem de falta de memória que você pode fazer

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

Sei que um par de maneira a causar a JVM de despejo de um arquivo de erro chamando métodos nativos (aqueles que são construídos na), mas a sua melhor provavelmente você não sabe como fazer isso.;)

MAPSERVER é uma grande fonte de acidentes.Você também pode falhar usando a interface JVMTI desde que precisa ser escrito em C/C++ também.

Se você criar uma thread processo que infinitamente gera mais threads (que geram mais threads, o que...) você vai, eventualmente, causar um erro de estouro de pilha da JVM em si.

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();
    }
}

Isso me deu a saída (depois de 5 minutos, assistir a sua memória 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:
# 

Mais curto?Use Robô classe para acionar as teclas CTRL+BREAK.Sim, eu vi isso quando eu estava tentando fechar meu programa sem fechar o console (Que não tinha a "saída" de funcionalidade).

Eu estou fazendo isso agora, mas não inteiramente certo como...:-) JVM (e meu app) às vezes apenas desaparecer completamente.Sem erros jogado, nada registrado.Vai do trabalho para não funcionando em todos os instantaneamente, sem aviso.

Faz essa contagem ?

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

Ele só funciona para Linux e Java 9.

Por algum motivo eu não consigo, ProcessHandle.current().destroyForcibly(); para não matar o JVM e lança java.lang.IllegalStateException com a mensagem destruir do processo atual não é permitido.

Se você alterar esse infinito loop for para uma chamada recursiva para a mesma função, então você teria que receber uma exceção de estouro de pilha:

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

public void causeStackOverflow() {
    causeStackOverflow();
}

Se um 'Crash', é algo que interrompe a jvm/programa de terminação normal, então um Onu-exceção manipulada poderia fazer isso.

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
  }

Então, isso depende de que tipo de ACIDENTE ?!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top