i have writen a servlet that recives a java script code and process it and returns the answer. for that i have used the java scripting API
in the code below if scrip
Here's some code showing the Future implementation and the Thread.stop() one. This is an interesting problem, and it points out the need for a hook in a ScriptEngine to be able to halt whatever script it's running for whatever reason. I wonder whether this would break the assumptions in most implementations since they assume eval()
will be executed in a single-threaded (blocking) environment?
Anyway, the results of executing the code below:
// exec with Thread.stop()
$ java ExecJavascript
Java: Starting thread...
JS: Before infinite loop...
Java: ...thread started
Java: Thread alive after timeout, stopping...
Java: ...thread stopped
(program exits)
// exec with Future.cancel()
$ java ExecJavascript 1
Java: Submitting script eval to thread pool...
Java: ...submitted.
JS: Before infinite loop...
Java: Timeout! trying to future.cancel()...
Java: ...future.cancel() executed
(program hangs)
Here's the full program:
import java.util.concurrent.*;
import javax.script.*;
public class ExecJavascript
{
private static final int TIMEOUT_SEC = 5;
public static void main( final String ... args ) throws Exception
{
final ScriptEngine engine = new ScriptEngineManager()
.getEngineByName("JavaScript");
final String script =
"var out = java.lang.System.out;\n" +
"out.println( 'JS: Before infinite loop...' );\n" +
"while( true ) {}\n" +
"out.println( 'JS: After infinite loop...' );\n";
if ( args.length == 0 ) {
execWithThread( engine, script );
}
else {
execWithFuture( engine, script );
}
}
private static void execWithThread(
final ScriptEngine engine, final String script )
{
final Runnable r = new Runnable() {
public void run() {
try {
engine.eval( script );
}
catch ( ScriptException e ) {
System.out.println(
"Java: Caught exception from eval(): " + e.getMessage() );
}
}
};
System.out.println( "Java: Starting thread..." );
final Thread t = new Thread( r );
t.start();
System.out.println( "Java: ...thread started" );
try {
Thread.currentThread().sleep( TIMEOUT_SEC * 1000 );
if ( t.isAlive() ) {
System.out.println( "Java: Thread alive after timeout, stopping..." );
t.stop();
System.out.println( "Java: ...thread stopped" );
}
else {
System.out.println( "Java: Thread not alive after timeout." );
}
}
catch ( InterruptedException e ) {
System.out.println( "Interrupted while waiting for timeout to elapse." );
}
}
private static void execWithFuture( final ScriptEngine engine, final String script )
throws Exception
{
final Callable<Object> c = new Callable<Object>() {
public Object call() throws Exception {
return engine.eval( script );
}
};
System.out.println( "Java: Submitting script eval to thread pool..." );
final Future<Object> f = Executors.newCachedThreadPool().submit( c );
System.out.println( "Java: ...submitted." );
try {
final Object result = f.get( TIMEOUT_SEC, TimeUnit.SECONDS );
}
catch ( InterruptedException e ) {
System.out.println( "Java: Interrupted while waiting for script..." );
}
catch ( ExecutionException e ) {
System.out.println( "Java: Script threw exception: " + e.getMessage() );
}
catch ( TimeoutException e ) {
System.out.println( "Java: Timeout! trying to future.cancel()..." );
f.cancel( true );
System.out.println( "Java: ...future.cancel() executed" );
}
}
}