Avertissement : Ces programmes sont des bombes clones (une sorte de forme moins dangereuse mais toujours dangereuse de bombe à fourche); en tant que tels, ne les exécutez pas sur un système de production sans bac à sable ni limites de ressources . Les bombes clones créent des threads dans une boucle (contrairement aux bombes fork, qui créent des processus dans une boucle), vous pouvez donc les arrêter simplement en tuant le processus en question (ce qui les rend beaucoup moins dangereux que les bombes fork, qui peuvent être très difficiles à nettoyer); mais ils bloqueront probablement la majeure partie de votre processeur jusqu'à ce que vous parveniez à le faire (ou jusqu'à ce que le programme gagne et se termine naturellement par lui-même). Demander à votre système d'exploitation de limiter la quantité de mémoire et le temps processeur que ces programmes sont autorisés à utiliser devrait créer un environnement sûr dans lequel les tester.
Java (OpenJDK 8) , 65 60 octets (avec une légère modification du wrapper)
Thread x=Thread.currentThread();new Thread(x::stop).start();
Essayez-le en ligne!
Nécessite que les deux instances de catch (Exception …)
la question soient remplacées par catch (Throwable …)
. Cela devrait en théorie être plus sûr, pas moins, mais cela permet à cette solution d'être possible.
J'ai économisé 5 octets sur la première version de cette réponse en utilisant une référence de méthode plutôt qu'un lambda.
Java 4, 104 octets (non testé, devrait fonctionner avec le wrapper d'origine)
final Thread x=Thread.currentThread();new Thread(){public void run(){x.stop(new Exception());}}.start();
Essayez-le en ligne! (le lien va vers une implémentation Java 8, donc ne fonctionnera pas)
En utilisant des fonctionnalités qui ont été supprimées des versions modernes de Java, il est possible de résoudre même la version du puzzle qui nécessite un Exception
. Probablement, au moins. (Java 4 est très ancien maintenant et je ne me souviens plus quelles fonctionnalités il contenait et ne contenait pas. Comme on peut le voir, il y avait beaucoup moins de fonctionnalités à l'époque à Java et il était donc plus détaillé; nous n'avions pas lambdas, j'ai donc dû créer une classe intérieure.)
Explications
La plupart des solutions à cette question sont en C # (avec une solution Java qui triche via l'utilisation de crochets non équilibrés comme forme d'injection de code, et une solution Perl qui n'est pas non plus en Java). J'ai donc pensé qu'il valait la peine d'essayer de montrer comment ce puzzle peut être résolu "correctement" en Java aussi.
Les deux programmes sont effectivement identiques (donc le fait que le premier programme fonctionne me donne une grande confiance que le deuxième programme fonctionnerait aussi, sauf si j'ai accidentellement utilisé une fonctionnalité non Java-4; a Thread#stop
été dépréciée dans Java 5).
La Thread#stop
méthode de Java fonctionne, en arrière-plan, en provoquant le lancement d'un objet jetable dans le thread en question. Le jetable prévu à cet effet est ThreadDeath
(un Error
, en particulier parce que les gens essaient souvent de détecter les exceptions et que les concepteurs de Java ne voulaient pas que cela se produise), bien qu'il vous permette de lancer quoi que ce soit (ou l'habitude; à un moment donné après que l'API ait été conçu, les concepteurs de Java ont réalisé que c'était une idée incroyablement mauvaise et ont supprimé la version de la méthode qui prend les arguments au clair). Bien sûr, même la version qui lance ThreadDeath
est une opération assez risquée pour laquelle vous pouvez faire peu de garanties (par exemple, cela vous permet de résoudre ce puzzle, quelque chose qui "ne devrait pas" être possible), donc vous n'êtes pas censé l'utiliser, mais à partir de Java 8, cela fonctionne toujours.
Ce programme fonctionne en générant un nouveau thread et en lui demandant de renvoyer de force une exception dans le thread principal. Si nous sommes chanceux, cela se fera à un moment où nous serons en dehors du catch
bloc interne (nous ne pouvons pas échapper au catch
bloc externe jusqu'à la fin du programme, car il y a une boucle autour de lui). Parce que nous avons déjà ajouté la boucle de manière pratique, il est économiseur d'octets d'utiliser simplement cette boucle pour nous permettre de continuer à créer des threads, dans l'espoir que l'un d'entre eux atteindra finalement le bon timing. Cela semble normalement se produire en quelques secondes.
(Remarque TIO: la version actuelle de TIO est assez encline à tuer ce programme au début de son exécution, probablement en raison de tous les threads créés. Il peut fonctionner sur TIO, mais ne fonctionne pas de manière fiable, si souvent quelques tentatives sont nécessaires pour obtenez la sortie "Vous avez gagné!".)