I'm sure it's possible to do this with batch, but it seems... sort of hacky, since you can load java classes natively in any java applications.
With that, I decided to try my hand at creating a small program designed for limiting the time that a given java console application can run. to my surprise, it seems to work great.
The basic idea is simple- use reflection to load a class name specified on the command line, find the main() method, create a new thread that invokes that method, put the first thread to sleep for the specified timeout period (not <exact> but probably closer then using ping...) and, check the state of the started thread after Sleep() returns; if the thread has terminated, the program finished, (or, there was an error running it, which will have be displayed). If not, the thread is still running and has failed to complete in the specified timeout. At that point, it is forced to stop with the stop() method (yes, I know, it's deprecated, but it's either that or leave it running in the background which especially in the case of my test program (which was just a for(;;);) meant that the CPU/a core was throttled to 100%.
Anyway, enough of that banter. The program itself consists of two classes:"javatest" which is the main program, and another class, "methodInvoker" which implements Runnable to allow for the second thread.
javatest.java:
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.util.*;
import java.io.*;
public class javatest{
/*
* arguments: classname timeout <args to pass to class>
*
*
*
*/
static String join(String[] passpathparts, String delimiter) {
StringBuilder builder = new StringBuilder();
for(int i = 0;i<passpathparts.length;i++)
{
builder.append(passpathparts[i]);
if(i<passpathparts.length-1)
builder.append(delimiter);
}
return builder.toString();
}
private static Class loadclassfromfile(String filename)
{
File file = new File(filename);
try {
// Convert File to a URL
String[] splitpathparts = filename.split("\\\\");
String[] passpathparts = new String[splitpathparts.length-1];
System.arraycopy(splitpathparts, 1, passpathparts, 0, splitpathparts.length-1);
String[] justpatharr = new String[splitpathparts.length-1];
System.arraycopy(splitpathparts, 0, justpatharr, 0, splitpathparts.length-1);
File dirpath = new File(join(justpatharr,"\\")+ "\\");
URL url = dirpath.toURI().toURL(); // file:/c:/myclasses/
URL[] urls = new URL[]{url};
// Create a new class loader with the directory
//
ClassLoader cl = new URLClassLoader(urls);
String classloadstring = join(passpathparts,".");
System.out.println("loading class..." + classloadstring);
// Load in the class; MyClass.class should be located in
// the directory file:/c:/myclasses/com/mycompany
Class returnme = cl.loadClass(classloadstring);
return returnme;
//Class cls = cl.loadClass("com.mycompany.MyClass");
} catch (MalformedURLException e) {
} catch (ClassNotFoundException e) {
}
return null;
}
public static void main(String[] args)
{
Thread runmethodthread=null;
if(args.length<2)
{
System.out.println("must pass at least 2 arguments");
return;
}
int timeout = Integer.parseInt(args[0]);
String[] passargs=new String[args.length-2];
System.arraycopy(args, 2, passargs, 0, args.length-2);
try{
java.lang.Class c;
if((new File(args[1] + ".class").exists() ))
{
c = loadclassfromfile(args[1]);
}
else
{
c = Class.forName(args[1]);
}
Method m[] = c.getDeclaredMethods();
Method mainmethod;
for (int i = 0; i < m.length; i++)
if(m[i].getName().equals("main"))
{
mainmethod = m[i];
runmethodthread = new java.lang.Thread(new methodinvoker(m[i],passargs));
break;
}
if(runmethodthread!=null)
{
runmethodthread.start();
System.out.println("Waiting " + timeout + " seconds for " + args[1] + "...");
Thread.sleep(timeout*1000);
if(runmethodthread.getState()==Thread.State.TERMINATED)
{
System.out.println("class " + args[1] + " has successfully completed.");
}
else
{
System.out.println("class " + args[1] + " did not complete in the timeout period.");
runmethodthread.stop();
}
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}
methodinvoker.java
import java.lang.reflect.Method;
public class methodinvoker implements Runnable
{
private Method mMethodInvoke;
private String[] args;
public methodinvoker(Method invokethis,String[] arguments)
{
mMethodInvoke=invokethis;
args = arguments;
}
@Override
public void run() {
try{
Object[] objargs ={args};
mMethodInvoke.invoke(null, objargs);
}
catch(Exception e)
{
if(e.getMessage()!=null)
System.out.println("error:" + e.getMessage()) ;
}
finally{
}
}
}
basically, once you've successfully compiled them (I'm using JDK version 1.6.0_17) you just need to start the javatest program with the proper arguments, such as:
java javatest 15 D:\folder\folder\classfile <arguments>
where <arguments> will be the arguments to pass on to the "main(String[] args)" routine of the specified class (from your batch and Unix scripts examples I am guessing that you are indeed passing something to these "Solver" programs). Also of note is that while it's quite possible to do so I was lazy and it only works when the specified classfile has a main() routine that accepts String[] args... that is, you cannot use this with a class that uses a main() routine without any arguments.
You might need to tweak the multiplier used in the call to Thread.sleep(), I didn't actually measure it but it seemed to take longer then 15 seconds when I passed 15, but I could have been imagining things.