Eu estava lendo um livro sobre habilidades de programação em que o autor pergunta ao entrevistado: "Como você colide com uma JVM?" Eu pensei que você poderia fazer isso escrevendo um loop for infinito que acabaria gastando toda a memória.
Alguém tem alguma ideia?
Respostas:
A coisa mais próxima de uma única "resposta" é
System.exit()
que finaliza a JVM imediatamente sem limpeza adequada. Mas, além disso, código nativo e exaustão de recursos são as respostas mais prováveis. Como alternativa, você pode procurar no bug tracker da Sun por erros na sua versão da JVM, alguns dos quais permitem cenários de travamento repetíveis. Costumávamos ter falhas semi-regulares quando chegávamos ao limite de 4 Gb de memória nas versões de 32 bits (geralmente usamos 64 bits agora).fonte
Eu não chamaria de lançar um OutOfMemoryError ou StackOverflowError uma falha. Essas são apenas exceções normais. Para travar realmente uma VM, existem três maneiras:
Para o último método, tenho um pequeno exemplo, que trava uma VM silenciosa do Sun Hotspot:
Isso leva a um estouro de pilha no GC, para que você não obtenha StackOverflowError, mas uma falha real, incluindo um arquivo hs_err *.
fonte
java.lang.OutOfMemoryError: GC overhead limit exceeded
JNI . De fato, com o JNI, travar é o modo padrão de operação. Você tem que trabalhar muito duro para não travar.
fonte
Usa isto:
Essa classe deve estar no caminho de classe de inicialização porque está usando código confiável, portanto, execute assim:
fonte
Field f = Unsafe.class.getDeclaredField( "theUnsafe" ); f.setAccessible( true ); unsafe = (Unsafe) f.get( null );
Funcionou muito bem para mim.Unsafe
é, por definição, "inseguro". Isso é meio trapaceiro.getDeclaredField
truque no JDK 8u131 no Linux x64, incluindo a produção dehs_err_pid*.log
aSIGSEGV
.Unsafe
não é uma fraude. O OP não está procurando uma solução 'limpa' para um problema de programação. Ele precisa da jvm para travar da maneira mais feia possível. Fazer coisas nativas desagradáveis é o que pode fazer isso acontecer, e é exatamente o queUnsafe
faz.Eu vim aqui porque também me deparei com essa pergunta no The Passionate Programmer , de 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 candidatos que entrevistam para uma posição que exige "realmente bons programadores de Java".
Especificamente, ele pergunta:
Programei em Java por mais de 15 anos e achei essa pergunta intrigante e injusta. Como outros já apontaram, o Java, como linguagem gerenciada, é projetado especificamente para não falhar . Obviamente, sempre existem erros da JVM, mas:
Como outros já mencionaram, algum código nativo via JNI é uma maneira de travar um JRE. Mas o autor mencionado especificamente em Java puro , então está pronto.
Outra opção seria alimentar os códigos de bytes falsos do JRE; é fácil despejar alguns dados binários de lixo em um arquivo .class e pedir ao JRE para executá-lo:
Isso conta? Quero dizer, o próprio JRE não caiu; ele detectou corretamente o código falso, relatou e saiu.
Isso nos deixa com os tipos mais óbvios de soluções, como explodir a pilha por recursão, ficar sem memória heap por meio de alocações de objetos ou simplesmente jogar
RuntimeException
. Mas isso apenas faz com que o JRE saia com umaStackOverflowError
exceção ou similar, o que novamente não é realmente um acidente .Então o que resta? Eu adoraria ouvir o que o autor realmente tinha em mente como uma solução adequada.
Atualização : Chad Fowler respondeu aqui .
PS: é um livro ótimo. Eu peguei o suporte moral enquanto aprendia Ruby.
fonte
Esse código travará a JVM de maneiras desagradáveis
fonte
InternalError
no JDK 1.8. A JVM não falha mais.A última vez que tentei isso faria:
Primeira parte do arquivo de log gerado:
fonte
Uma implementação perfeita da JVM nunca falha.
Para travar uma JVM, além da JNI, você precisa encontrar um bug na própria VM. Um loop infinito apenas consome CPU. A alocação infinita de memória deve causar apenas OutOfMemoryError em uma JVM bem construída. Isso provavelmente causaria problemas para outros encadeamentos, mas uma boa JVM ainda não deve travar.
Se você encontrar um bug no código-fonte da VM e, por exemplo, causar uma falha de segmentação no uso de memória da implementação da VM, poderá travá-lo.
fonte
Se você deseja travar a JVM - use o seguinte no Sun JDK 1.6_23 ou abaixo:
Isso ocorre devido a um erro no Sun JDK - também encontrado no OpenJDK. Isso foi corrigido a partir do Oracle JDK 1.6_24 em diante.
fonte
Depende do que você quer dizer com acidente.
Você pode fazer uma recursão infinita para que fique sem espaço na pilha, mas isso trava "normalmente". Você receberá uma exceção, mas a própria JVM estará lidando com tudo.
Você também pode usar o JNI para chamar código nativo. Se você não fizer isso da maneira certa, poderá travar com força. Depurar essas falhas é "divertido" (acredite, eu tive que escrever uma grande DLL C ++ que chamamos de um applet java assinado). :)
fonte
O livro Java Virtual Machine de Jon Meyer tem um exemplo de uma série de instruções de bytecode que fizeram com que a JVM fizesse core dump. Não consigo encontrar minha cópia deste livro. Se alguém por aí tiver um, procure e publique a resposta.
fonte
em winxpsp2 w / wmp10 jre6.0_7
Desktop.open (uriToAviOrMpgFile)
Isso faz com que um thread gerado lance um Throwable não capturado e trava o ponto de acesso
YMMV
fonte
O hardware quebrado pode travar qualquer programa. Certa vez, um aplicativo travou de forma reproduzível em uma máquina específica enquanto funcionava bem em outras máquinas com a mesma configuração exata. Acontece que a máquina tinha RAM com defeito.
fonte
maneira mais curta possível :)
fonte
Exception in thread "main" java.lang.StackOverflowError at Test.main
. Estou usando jdk1.8.0_65Não é um acidente, mas está mais próximo do que a resposta aceita do uso
System.exit
Você pode interromper a JVM chamando
Runtime.getRuntime().halt( status )
De acordo com os documentos: -
fonte
Aqui está uma explicação detalhada sobre o que faz com que a JVM faça o dump principal (ou seja, falha): http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_17534
fonte
Se você quiser fingir que ficou sem memória, pode fazer
Conheço algumas maneiras de fazer com que a JVM despeje um arquivo de erro chamando métodos nativos (aqueles que são incorporados), mas provavelmente é melhor você não saber como fazer isso. ;)
fonte
Se você definir uma falha como um processo interrompido devido a uma situação não tratada (por exemplo, nenhuma exceção ou erro do Java), isso não poderá ser feito no Java (a menos que você tenha permissão para usar a classe sun.misc.Unsafe). Esse é o ponto principal do código gerenciado.
Falhas típicas no código nativo acontecem desmarcando os ponteiros para áreas de memória incorretas (endereço nulo ou desalinhado). Outra fonte pode ser instruções ilegais da máquina (códigos de operação) ou sinais não manipulados de chamadas de biblioteca ou kernel. Ambos podem ser acionados se a JVM ou as bibliotecas do sistema tiverem erros.
Por exemplo, código JIT (gerado), métodos nativos ou chamadas do sistema (driver gráfico) podem ter problemas que levam a falhas reais (era bastante comum ocorrer uma falha quando você usava as funções ZIP e elas ficavam sem memória). Nesses casos, o manipulador de falhas da JVM entra em ação e despeja o estado. Também poderia gerar um arquivo principal do sistema operacional (Dr. Watson no Windows e dump principal no * nix).
No Linux / Unix, você pode facilmente travar a JVM enviando um sinal para o processo em execução. Nota: você não deve usar
SIGSEGV
isso, pois o Hotspot captura esse sinal e o lança novamente como NullPointerException na maioria dos lugares. Portanto, é melhor enviar umSIGBUS
por exemplo.fonte
JNI é uma grande fonte de falhas. Você também pode travar usando a interface JVMTI, pois ela também precisa ser gravada em C / C ++.
fonte
Se você criar um processo de encadeamento que gera infinitamente mais encadeamentos (que geram mais encadeamentos, que ...), você eventualmente causará um erro de estouro de pilha na própria JVM.
Isso me deu a saída (depois de 5 minutos, observe seu carneiro)
fonte
Se por "travamento" você quer dizer um cancelamento abrupto da JVM, como faria com que a JVM escrevesse em seu hs_err_pid% p.log , você pode fazê-lo dessa maneira.
Defina the-Xmx arg como um valor minúsculo e diga à JVM para forçar uma falha na memória excedente:
Para ficar claro, sem o segundo argumento acima, isso resultaria no término da jvm com um OutOfMemoryError, mas não "travaria" ou abortaria abruptamente a jvm.
Essa técnica se mostrou útil quando eu estava tentando testar o argumento JVM -XX: ErrorFile, que controla onde esse log hs_err_pid deve ser gravado. Eu encontrei este post aqui, enquanto tentava encontrar maneiras de forçar esse acidente. Mais tarde, quando descobri que o acima funcionava como o mais fácil para minha necessidade, queria adicioná-lo à lista aqui.
Finalmente, FWIW, se alguém puder testar isso quando já tiver um valor -Xms definido em seus argumentos (para um valor maior que o acima), convém remover ou alterar isso também, ou você não sofrerá uma falha, mas simplesmente uma falha na inicialização da jvm, relatando "Tamanho inicial do heap configurado para um valor maior que o tamanho máximo do heap". (Isso não seria óbvio se a JVM fosse executada como serviço, como em alguns servidores de aplicativos. Novamente, isso me mordeu, então eu queria compartilhá-lo.)
fonte
Se você alterar esse loop for infinito para uma chamada recursiva para a mesma função, receberá uma exceção de estouro de pilha:
fonte
Estou fazendo isso agora, mas não tenho muita certeza de como ... :-) Às vezes, a JVM (e meu aplicativo) desaparece completamente. Nenhum erro lançado, nada registrado. Passa do trabalho para não funcionar instantaneamente sem aviso.
fonte
Mais curto? Use a classe Robot para acionar CTRL + BREAK. Vi isso quando estava tentando fechar meu programa sem fechar o console (ele não tinha a funcionalidade de 'saída').
fonte
Isso conta?
Funciona apenas para Linux e Java 9.
Por alguma razão eu não entendo,
ProcessHandle.current().destroyForcibly();
não mata a JVM e lançajava.lang.IllegalStateException
com a mensagem destruir do processo atual não permitido .fonte
Correndo para esse problema ao tentar replicar a falha da JVM.
O Jni funciona, mas precisa ser ajustado para diferentes plataformas. Eventualmente, eu uso essa combinação para causar falha na JVM
-XX:+CrashOnOutOfMemoryError
long[] l = new long[Integer.MAX_VALUE];
para acionar o OOMA JVM falhará e gerará o log de falha.
fonte
Se um 'Crash' é algo que interrompe o jvm / programa da finalização normal, uma exceção Un-handled pode fazer isso.
Então, depende de que tipo de CRASH ?!
fonte
ArithmeticException
são