J'ai écrit un servlet qui recette un code de script Java et le traite et renvoie la réponse. Pour cela, j'ai utilisé l'API de script Java
dans le code ci-dessous si script = "Imprimer (" Bonjour, Monde ")"; Le code prendra correctement imprimer correctement "Hello World". mais si script = "alors que (vrai);" Le script va boucler sans fin. P>
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// evaluate JavaScript code from String
engine.eval(script);
}
}
7 Réponses :
Exécutez l'évaluation dans un thread séparé et interrost-le après 15 ans à l'aide de thread.Interrupt (). Cela arrêtera l'EVAL et lancera une exception interrompue, que vous pouvez attraper et retourner le statut d'échec.
Une meilleure solution serait d'avoir une sorte d'interface asynchée au moteur de script, mais aussi loin que je pouvais voir que cela ne le voit pas. existent. p>
EDIT: P>
Comme Sfussenegger a souligné, l'interruption ne fonctionne pas avec le moteur de script, car elle ne peut jamais dormir ou n'entre aucun état d'attente pour être interrompu. Le Niether pourrait-je trouver n'importe quel rappel périodique dans les objets ScriptContext ou les objets de liaison pouvant être utilisés comme crochet pour vérifier les interruptions. Il y a une méthode qui fonctionne, bien que: thread.stop (). Il est obsolète et inhéremment à un certain nombre de raisons, mais je posterai le code de test ici avec la mise en œuvre de Chris Winters à titre de comparaison. La version de Chris effectuera le délai d'attente, mais laissez le fil d'arrière-plan en marche, l'interruption () ne fait que rien et la butée () tue le fil et reprend le contrôle au fil principal: P>
import javax.script.*;
import java.util.concurrent.*;
class ScriptRunner implements Runnable {
private String script;
public ScriptRunner(String script) {
this.script = script;
}
public ScriptRunner() {
this("while(true);");
}
public void run() {
try {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// evaluate JavaScript code from String
System.out.println("running script :'" + script + "'");
engine.eval(script);
System.out.println("stopped running script");
} catch(ScriptException se) {
System.out.println("caught exception");
throw new RuntimeException(se);
}
System.out.println("exiting run");
}
}
public class Inter {
public void run() {
try {
Executors.newCachedThreadPool().submit(new ScriptRunner()).get(15, TimeUnit.SECONDS);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
public void run2() {
try {
Thread t = new Thread(new ScriptRunner());
t.start();
Thread.sleep(1000);
System.out.println("interrupting");
t.interrupt();
Thread.sleep(5000);
System.out.println("stopping");
t.stop();
} catch(InterruptedException ie) {
throw new RuntimeException(ie);
}
}
public static void main(String[] args) {
new Inter().run();
}
}
-1 Si la bande de roulement n'attend pas, il n'y aura pas d'exception. Par conséquent, cela ne fonctionnera pas avec une boucle sans fin. Le code devrait vérifier thread.CurrentThread (). Interrompu () Code> Pour que vos suggestions fonctionnent.
ARGH, a manqué celui-là. Cela ne laisse que l'arrêt obsolète () je crois?
Thread.stop () pourrait causer une demande de crash (arrive avec moi systématiquement dans un environnement important) si ce thread traite des appels autochtones.
Voici quelques codes montrant la future implémentation et le thread.stop () un. C'est un problème intéressant, et cela souligne la nécessité d'un crochet dans une scriptengine pour pouvoir arrêter le script que cela fonctionne pour une raison quelconque. Je me demande si cela briserait les hypothèses dans la plupart des implémentations, car elles supposent que Quoi qu'il en soit, les résultats de l'exécution du code ci-dessous: p> voici le programme complet: p> eval () code> seront exécutés dans un environnement unique (blocage)?
Cela reprend le contrôle après 15 secondes avec une exception de délai d'attente, mais laisse le fil d'arrière-plan en cours d'exécution, alors la question de savoir comment l'interrompre reste.
Duh! Merci pour le commentaire, a ajouté la future annulation.
Bonjour, merci pour la solution élégante, mais même après l'annulation future, le thread de fond est toujours en train de consommer les ressources du processeur. Donc, la question reste toujours ..
Après l'annulation de l'avenir, il est vrai que le fil d'arrière-plan continue à courir, mais j'ai remarqué après un moment, il est fini par tuer. Est-ce attendu?
OK, cela fonctionne parfaitement si vous appelez exécutorservice.shutdown () dans un blocage enfin après avoir manipulé toutes ces exceptions. À votre santé.
@Atigofernandez exécutorservice.shutdown () ne résout pas le problème. De docs.oracle.com / Javase / 7 / Docs / API / Java / UTIL / ... , "Il n'y a pas de garantie au-delà des tentatives des meilleurs efforts pour arrêter de traiter activement des tâches. Par exemple, des implémentations typiques annuleront via Thread.Interrupt ( ), toute tâche qui omet de réagir aux interruptions peut ne jamais se terminer. " Mes threads ne se terminent pas, même après avoir appelé l'arrêt () ou Shutdownow ().
Si vous ne voulez pas utiliser de thread.stop () (et vous devriez vraiment être), il ne semble pas y avoir aucun moyen d'atteindre votre besoin avec l'API Javax.script. p>
Si vous utilisez directement le moteur de rhinocéros et les performances réelles ne sont pas trop importantes, vous pouvez implémenter un crochet dans le contexte.ObServeInStructureCount pour interrompre ou terminer prématurément l'exécution du script. Le crochet est invoqué pour chaque instruction JavaScript exécutée après avoir atteint le seuil (nombre d'instructions) défini avec seinstrucanceOserverthold. Vous devez mesurer le temps d'exécution vous-même, car vous n'êtes fourni que le nombre d'instructions exécutées et que cela peut avoir un impact pertinent sur la performance. Je ne suis pas sûr, mais le crochet peut également être invoqué que si le moteur de script s'exécute en mode interprété et non si le code JavaScript est compilé. P>
Context.ObServeInStructionCount n'est appelé en mode interprété, de sorte que c'est une performance significative. J'espère bien que l'équipe de rhinocéros est une meilleure façon. P>
Je sais que c'est un fil plus ancien, mais j'ai une solution plus directe pour arrêter JavaScript Eval: appelez la fonction "Quitter" que Nashorn fournit.
à l'intérieur de la classe I Utilisé pour exécuter le moteur de script, j'inclus : p> maintenant, appelez: p> Le script s'arrête immédiatement. P> p>
Downvoting. L'appel "EXIT" ne quitte pas le moteur de script, mais l'ensemble de la JVM.
Je ne suis pas d'accord; Ce n'était pas le cas dans mon projet. Le moteur de script s'est arrêté, le reste de mon programme a continué à fonctionner sur la JVM.
Les scripts Nashorn sont compilés à des "fichiers" .Class et chargés à la volée. Ainsi, l'évaluation du script est similaire à la chargement d'une java compilée et de la même manière. Sauf si vous programmez explicitement pour interruption, vous ne pouvez pas arrêter l'évaluation du script. Il n'y a pas d'interprète "script" qui "sondages" pour l'état d'interruption. Vous devez expliquer explicitement le thread.sleep ou d'autres API Java qui sont interrompues d'un autre fil. P>
Un vieux fil, mais celui que je suis tombé en premier en essayant de résoudre ce problème, je voudrais donc y répondre ici plutôt que de trouver un plus récent.
Une autre façon qui évite d'utiliser l'arrêt Java.Lang.thread. la méthode consiste à jeter une exception dans le JavaScript: p> et pas em> l'attraper dans le script mais laissez-le tomber à Java et l'attraper (le code encore en cours d'exécution) Code Java: P> try{
eval(script);
}catch(ScriptException ex) {
if(ex.getMessage().startsWith("_EXIT")) {
// do nothing but exit nashorn
} else {
// handle the exception
}
}