Je lisais un livre sur les compétences en programmation dans lequel l'auteur demande à la personne interrogée: "Comment faire planter une JVM?" Je pensais que vous pouviez le faire en écrivant une boucle for infinie qui finirait par utiliser toute la mémoire.
Quelqu'un a une idée?
Réponses:
La chose la plus proche d'une seule "réponse" est de
System.exit()
mettre fin immédiatement à la machine virtuelle Java sans nettoyage approprié. Mais à part cela, le code natif et l'épuisement des ressources sont les réponses les plus probables. Sinon, vous pouvez aller chercher sur le bug tracker de Sun les bogues dans votre version de la JVM, dont certains permettent des scénarios de crash répétables. Nous avions l'habitude d'avoir des plantages semi-réguliers à l'approche de la limite de mémoire de 4 Go sous les versions 32 bits (nous utilisons généralement 64 bits maintenant).la source
Je n'appellerais pas lancer une OutOfMemoryError ou StackOverflowError un crash. Ce ne sont que des exceptions normales. Pour vraiment planter une VM, il y a 3 façons:
Pour la dernière méthode, j'ai un court exemple, qui fera planter une VM Sun Hotspot bien silencieusement:
Cela conduit à un débordement de pile dans le GC donc vous n'obtiendrez pas StackOverflowError mais un vrai crash incluant un fichier hs_err *.
la source
java.lang.OutOfMemoryError: GC overhead limit exceeded
JNI . En fait, avec JNI, le crash est le mode de fonctionnement par défaut. Vous devez travailler très dur pour qu'il ne plante pas.
la source
Utilisez ceci:
Cette classe doit être sur le chemin de classe de démarrage car elle utilise du code de confiance, alors exécutez comme ceci:
la source
Field f = Unsafe.class.getDeclaredField( "theUnsafe" ); f.setAccessible( true ); unsafe = (Unsafe) f.get( null );
très bien fonctionné pour moi.Unsafe
est, par définition, «dangereux». C'est un peu une triche.getDeclaredField
Confirmation de l' utilisation de l' astuce dans JDK 8u131 sous Linux x64, y compris la production d'hs_err_pid*.log
un fichierSIGSEGV
.Unsafe
n'est pas une triche. OP ne cherche pas une solution «propre» à un problème de programmation. Il a besoin que la jvm plante de la manière la plus laide possible. Faire de mauvaises choses indigènes est ce qui peut y arriver, et c'est exactement ce quiUnsafe
fait.Je suis venu ici parce que j'ai aussi rencontré cette question dans The Passionate Programmer , de Chad Fowler. Pour ceux qui n'ont pas accès à une copie, la question est formulée comme une sorte de filtre / test pour les candidats en entrevue pour un poste nécessitant de «très bons programmeurs Java».
Plus précisément, il demande:
J'ai programmé en Java pendant plus de 15 ans et j'ai trouvé cette question à la fois déroutante et injuste. Comme d'autres l'ont souligné, Java, en tant que langage géré, est spécifiquement conçu pour ne pas planter . Bien sûr, il y a toujours des bogues JVM, mais:
Comme d'autres l'ont mentionné, du code natif via JNI est un moyen sûr de planter un JRE. Mais l'auteur a spécifiquement mentionné en Java pur , donc c'est fini.
Une autre option consisterait à alimenter les faux codes d'octets JRE; il est assez facile de vider des données binaires inutiles dans un fichier .class et de demander au JRE de l'exécuter:
Cela compte-t-il? Je veux dire que le JRE lui-même ne s'est pas écrasé; il a correctement détecté le faux code, l'a signalé et est sorti.
Cela nous laisse avec les types de solutions les plus évidents tels que le gonflement de la pile via la récursivité, le manque de mémoire du tas via des allocations d'objets ou simplement le lancement
RuntimeException
. Mais cela provoque simplement la fermeture du JRE avec uneStackOverflowError
exception ou une exception similaire, ce qui, encore une fois, n'est pas vraiment un crash .Alors que reste-t-il? J'adorerais vraiment entendre ce que l'auteur avait vraiment en tête comme solution appropriée.
Mise à jour : Chad Fowler a répondu ici .
PS: c'est un livre autrement génial. Je l'ai pris pour un soutien moral tout en apprenant Ruby.
la source
Ce code plantera la JVM de manière désagréable
la source
InternalError
JDK 1.8. JVM n'échoue plus.La dernière fois que j'ai essayé, cela le ferait:
Première partie du fichier journal généré:
la source
Une implémentation JVM parfaite ne plantera jamais.
Pour planter une JVM, à part JNI, vous devez trouver un bogue dans la VM elle-même. Une boucle infinie consomme simplement du processeur. L'allocation de mémoire à l'infini devrait simplement provoquer des OutOfMemoryError dans une JVM bien construite. Cela poserait probablement des problèmes pour d'autres threads, mais une bonne JVM ne devrait toujours pas planter.
Si vous pouvez trouver un bogue dans le code source de la VM, et par exemple provoquer une erreur de segmentation dans l'utilisation de la mémoire de l'implémentation de la VM, vous pouvez en fait la planter.
la source
Si vous souhaitez planter JVM, utilisez ce qui suit dans Sun JDK 1.6_23 ou version antérieure:
Cela est dû à un bogue dans Sun JDK - également trouvé dans OpenJDK. Ce problème est résolu à partir d'Oracle JDK 1.6_24.
la source
Cela dépend de ce que vous entendez par crash.
Vous pouvez faire une récursion infinie pour le faire manquer d'espace dans la pile, mais cela plantera "gracieusement". Vous obtiendrez une exception, mais la JVM elle-même gérera tout.
Vous pouvez également utiliser JNI pour appeler du code natif. Si vous ne le faites pas correctement, vous pouvez le rendre difficile. Déboguer ces plantages est "amusant" (croyez-moi, j'ai dû écrire une grosse DLL C ++ que nous appelons à partir d'une applet java signée). :)
la source
Le livre Java Virtual Machine de Jon Meyer présente un exemple d'une série d'instructions de bytecode qui ont provoqué le vidage de mémoire de la JVM. Je ne trouve pas mon exemplaire de ce livre. Si quelqu'un en a un, veuillez le rechercher et poster la réponse.
la source
sur winxpsp2 avec wmp10 jre6.0_7
Desktop.open (uriToAviOrMpgFile)
Cela provoque un thread généré pour lancer un Throwable non intercepté et bloque le hotspot
YMMV
la source
Un matériel cassé peut planter n'importe quel programme. Une fois, j'ai eu un crash d'application reproductible sur une machine spécifique tout en fonctionnant correctement sur d'autres machines avec exactement la même configuration. Il s'avère que cette machine avait une RAM défectueuse.
la source
le plus court possible :)
la source
Exception in thread "main" java.lang.StackOverflowError at Test.main
. J'utilise jdk1.8.0_65Pas un crash, mais plus proche d'un crash que la réponse acceptée de l'utilisation
System.exit
Vous pouvez arrêter la JVM en appelant
Runtime.getRuntime().halt( status )
Selon la documentation: -
la source
voici une explication détaillée sur les causes du vidage de mémoire de la JVM (c.-à-d. plantage): http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_17534
la source
Si vous voulez faire comme si vous n'aviez plus de mémoire, vous pouvez le faire
Je connais deux façons de provoquer le vidage d'un fichier d'erreur par la JVM en appelant des méthodes natives (celles qui sont intégrées), mais il est probablement préférable que vous ne sachiez pas comment faire cela. ;)
la source
Si vous définissez un crash comme un abandon de processus en raison d'une situation non gérée (c'est-à-dire pas d'exception ou d'erreur Java), cela ne peut pas être fait depuis Java (à moins que vous n'ayez l'autorisation d'utiliser la classe sun.misc.Unsafe). C'est tout l'intérêt du code managé.
Les plantages typiques dans le code natif se produisent en dé-référençant des pointeurs vers des zones de mémoire incorrectes (adresse nulle ou mal aligné). Une autre source pourrait être des instructions machine illégales (opcodes) ou des signaux non gérés provenant d'appels de bibliothèque ou de noyau. Les deux peuvent être déclenchés si la JVM ou les bibliothèques système ont des bogues.
Par exemple, le code JITed (généré), les méthodes natives ou les appels système (pilote graphique) peuvent avoir des problèmes menant à de vrais plantages (il était assez courant d'avoir un crash lorsque vous utilisiez des fonctions ZIP et qu'elles manquaient de mémoire). Dans ces cas, le gestionnaire de crash de la JVM démarre et vide l'état. Il pourrait également générer un fichier core du système d'exploitation (Dr. Watson sur Windows et core dump sur * nix).
Sous Linux / Unix, vous pouvez facilement faire planter une JVM en lui envoyant un signal au processus en cours d'exécution. Remarque: vous ne devez pas utiliser
SIGSEGV
pour cela, car Hotspot capte ce signal et le relance comme une NullPointerException dans la plupart des endroits. Il vaut donc mieux envoyer unSIGBUS
par exemple.la source
JNI est une source importante de plantages. Vous pouvez également planter en utilisant l'interface JVMTI car cela doit également être écrit en C / C ++.
la source
Si vous créez un processus de thread qui génère infiniment plus de threads (qui génèrent plus de threads, ce qui ...), vous finirez par provoquer une erreur de débordement de pile dans la JVM elle-même.
Cela m'a donné la sortie (après 5 minutes, surveillez votre bélier)
la source
Si par "crash" vous entendez un abandon brutal de la JVM, comme cela provoquerait l'écriture de la JVM dans son hs_err_pid% p.log , vous pouvez le faire de cette façon.
Définissez l'argument-Xmx sur une valeur minuscule et indiquez à la machine virtuelle Java de forcer un crash en cas de mémoire insuffisante:
Pour être clair, sans le deuxième argument ci-dessus, il en résulterait simplement que le jvm se terminerait par une OutOfMemoryError, mais il ne "planterait" pas ou n'abandonnerait pas brusquement le jvm.
Cette technique s'est avérée utile lorsque j'essayais de tester l'arg JVM -XX: ErrorFile, qui contrôle où un tel journal hs_err_pid doit être écrit. J'avais trouvé ce post ici, en essayant de trouver des moyens de forcer un tel crash. Quand j'ai trouvé plus tard que ce qui était le plus simple pour mon besoin, j'ai voulu l'ajouter à la liste ici.
Enfin, FWIW, si quelqu'un peut tester cela alors qu'il a déjà une valeur -Xms définie dans vos arguments (à une valeur plus grande que ci-dessus), vous voudrez supprimer ou modifier cela également, ou vous n'obtiendrez pas un plantage mais simplement un échec du démarrage du jvm, signalant «La taille initiale du tas est définie sur une valeur supérieure à la taille maximale du tas». (Cela ne serait pas évident si vous exécutiez la JVM en tant que service, comme avec certains serveurs d'applications. Encore une fois, cela m'a mordu, alors je voulais le partager.)
la source
Si vous changez cette boucle for infinie en un appel récursif à la même fonction, vous obtiendrez une exception de débordement de pile:
la source
Je le fais maintenant, mais je ne sais pas vraiment comment ... :-) JVM (et mon application) disparaissent parfois complètement. Aucune erreur générée, rien enregistré. Passe de travailler à ne pas fonctionner du tout instantanément sans avertissement.
la source
Le plus court? Utilisez la classe Robot pour déclencher CTRL + BREAK. J'ai repéré cela lorsque j'essayais de fermer mon programme sans fermer la console (il n'avait pas de fonctionnalité de «sortie»).
la source
Cela compte-t-il?
Cela ne fonctionne que pour Linux et à partir de Java 9.
Pour une raison quelconque, je n'obtiens pas,
ProcessHandle.current().destroyForcibly();
ne tue pas la JVM et jettejava.lang.IllegalStateException
avec le message la destruction du processus actuel non autorisée .la source
Vous rencontrez ce problème lors de la tentative de réplication du plantage de la JVM.
Jni fonctionne, mais il doit être peaufiné pour différentes plates-formes. Finalement, j'utilise cette combinaison pour faire planter JVM
-XX:+CrashOnOutOfMemoryError
long[] l = new long[Integer.MAX_VALUE];
pour déclencher le MOOEnsuite, JVM plantera et générera le journal des plantages.
la source
Si un «Crash» est quelque chose qui interrompt le jvm / programme de l'arrêt normal, alors une exception non gérée pourrait le faire.
Alors, cela dépend de quel type de CRASH?!
la source
ArithmeticException
est