I am invoking the main class of a .class contained in the same folder from my Java code. That main is void, and I want to check whether it was successful or not by checking its exit status:
...
String[] arguments = new String[]{"a", "b"};
AnotherClass.main(arguments);
...
Any idea on how, being that AnotherClass.main(arguments); does not return anything?
Thank you.
Even better idea -- instead of trying to call a main method, instead create a method in your other class called testMain() which does the same thing as main except it returns the exit code instead of exiting.
System.exit() called in that main method will shut down your entire program. You want to run the other main in another thread and find the exit code for that thread.
Build the other program (name the jar AnotherClass.jar), add the jar to your path and try this:
int exitCode;
try {
Process process = Runtime.getRuntime().exec("java AnotherClass.jar",new String[]{"arg1","arg2"});
exitCode = process.waitFor();
System.out.println(exitCode);
} catch (IOException e) {
System.out.println("IO Error: " + e);
} catch (InterruptedException e) {
System.out.println("Inturrupted: " + e);
}
EDIT: The following will not work at all; System.exit() kills all threads.
This code will run another main method in a new thread, and when it exits it will not harm your current program.
Thread anotherProgram = new Thread(new Runnable() {
#Override
public void run() {
AnotherClass.main(new String[]{"foo","bar"});
}
});
anotherProgram.start();
If you mean the exit code parameter to System.exit(int status), you cannot access it, as when it is called by some part of the main method (or subsequently executed code), your application is exited, and so there is nothing left running to get at the code.
The only way to check the exit code of an application is using the OS, e.g. the $? environment variable in unix tells you the exit code of the last application to terminate in that session.
Edit: Here's an example using ProcessBuilder to do so:
Process p = new ProcessBuilder(System.getProperty("java.home")+"/bin/java", "fully.qualified.package.to.AnotherClass").start();
Integer exitCode = null;
while (exitCode == null) {
try {
exitCode = p.waitFor();
} catch (InterruptedException e) {
// handle e
}
}
Related
this is my first question here.
I am trying to run parallel python scripts (that is multiple instances of a same script) from java periodically using the ScheduledThreadPoolExecutor. What i tried to do was using the ProcessBuilder class. To test the concept i have put first script into infinite loop while the second writes something to file and exits. Python scripts i need to make should be identical to each other so i tried to run these two from multiple instaces of a same class that implements runnable.
However the second script never starts. I managed to solve this by creating many classes that have exactly same runnable. But it seems highly impractical to have 10-20 classes that are same. So can i do this somehow within one runnable?
Here is the code that shows how i tried to run scripts using the ProcessBuilder:
public class TestScripts{
public static void main(String[] args){
ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(2);
threadPool.scheduleAtFixedRate(new MyTask1(), 1,2, TimeUnit.SECONDS);
threadPool.scheduleAtFixedRate(new MyTask1(), 1,2, TimeUnit.SECONDS);
}
}
class MyTask1 implements Runnable{
public void run(){
System.out.println("Task1 is running");
ProcessBuilder processBuilder = new ProcessBuilder("C:\\Python27\\python.exe",
"C:\\Python27\\test.py");
ProcessBuilder processBuilder2 = new ProcessBuilder("C:\\Python27\\python.exe",
"C:\\Python27\\test2.py");
processBuilder.redirectOutput(Redirect.INHERIT);
try {
Process process = processBuilder.start();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Process process2 = processBuilder.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
There is a typo in the line starting 2nd process:
Process process2 = processBuilder.start();
should be of course:
Process process2 = processBuilder2.start();
Besides you are scheduling 2 tasks, where each task starts 2 processes. So each 2 seconds there are 4 processes started (2x test.py, 2x test2.py). If I understand correctly what you're trying to do, scheduling only one MyTask1 should be enough.
Hi I am wondering how I could use a timer to destroy a process if it elapses a predefined time period in milisecs.
Currently I have a method which gets the thread from runtime
Runtime runtime = Runtime.getRuntime();
I then create separate process to execute a command using the runtime
Process process = runtime.exec(comman); //where command is a string with a defined command
I then handle the normal/error output streams before calling:
process.waitFor();
this waits for the process to terminate if it hasn't already.
My question is, how can I go about using a timer to terminate the process before it has finished, i.e. by calling:
process.destroy;
Basically, if the process works for more than a certain length of time, I want to destroy it prematurely.
I would then throw an InterruptedException if it was destroyed because of over runing.
I was told that using a timer would be the best way to achieve this, but wasnt sure if this was the case?
Any help would be hugely appreciated.
try
final Process p = ...
final Thread mainThread = Thread.currentThread();
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(1000);
p.destroy();
mainThread.interrupt();
} catch (InterruptedException e) {
}
};
};
p.waitFor();
if (mainThread.isInterrupted()) {
throw new InterruptedException();
}
t.interrupt();
My Goal
I am attempting to make a Java program in which a user can select any .class or .jar file from their computer. My program will then pop up a JInternalFrame with a JEditorPane in it as the console, capturing any console output from the user's program. When the user's program closes (calls System.exit(int status);), my program must not close along with it. My program might also have such features as a button to immediately stop the user's program and others an IDE would. My program need not compile Java code, only run .class and .jar files.
My Experience
I have made a small test version of this program wherein I got two specific files from a package and had the user click one of two buttons, each representing one of the two programs. A press of a button calls the following method:
private void run(Class runnable)
{
java.lang.reflect.Method[] m = runnable.getMethods();
boolean hasMain = false;
for (int i = 0; i < m.length; i++)
{
if (m[i].getName().equals("main") && m[i].getParameterTypes()[0].isArray() && m[i].getParameterTypes()[0].getName().contains("java.lang.String"))
try
{
Object invoke = m[i].invoke(null, (Object)globalArgs);
hasMain = true;
hub.setExtendedState(Hub.ICONIFIED);
numPrograms++;
}
catch (Throwable t)
{
java.util.logging.Logger.getLogger(Hub.class.getName()).log(java.util.logging.Level.SEVERE, null, t);
javax.swing.JOptionPane.showMessageDialog(null, "Could not run " + runnable.getName(), "Error in invocation", javax.swing.JOptionPane.ERROR_MESSAGE);
}
finally
{
break;
}
}
if (!hasMain)
javax.swing.JOptionPane.showMessageDialog(null, runnable.getName()
+ " does not have a public static main method that\nreturns void and takes in an array of Strings",
"No main method", javax.swing.JOptionPane.ERROR_MESSAGE);
}
This method successfully calls either program's main method and runs a copy of said program. However, when any of the programs this hub has started calls the System.exit(int status) command, the hub closes, too. Also, I haven't the slightest clue as to how to capture console output.
My Questions
Does anyone have any experience or advice they would be willing to share to help me make a fully-functional program that can...
Open and run a compiled Java file (remember that .jar files may have more than one class with main(String[] args) method)
Catch System.exit(int status); so that the hub program handles the internal program's exiting
Catch new java.io.PrintStream().println(Object o) and similar calls and place their output in a JEditorPane
Make a button that, when pressed, stops the internal program from running
Possibly make all JFrames the internal program uses into JInternalFrames and place them in a JDesktopPane
If you don't want the other program (which you call through it's main method) to be able to shut down the JVM you're running in, you have, as I see it, three options:
1. Using a SecurityManager
Set up the SecurityManager so that it prevents the System.exit call:
public class Test {
public static void main(String args[]) {
SecurityManager sm = System.getSecurityManager();
System.setSecurityManager(new SecurityManager() {
#Override
public void checkExit(int status) {
throw new SecurityException("Client program exited.");
}
});
try {
System.out.println("hello");
System.exit(0);
System.out.println("world");
} catch (SecurityException se) {
System.out.println(se.getMessage());
}
}
}
Prints:
hello
Client program exited.
This is probably the nicest solution. This is the way application servers prevent an arbitrary servlet from terminating the entire server.
2. Separate JVM
Run the other program in a separate JVM, using for instance ProcessBuilder
import java.io.*;
public class Test {
public static void main(String args[]) throws IOException {
ProcessBuilder pb = new ProcessBuilder("java", "other.Program");
pb.redirectErrorStream();
Process p = pb.start();
InputStream is = p.getInputStream();
int ch;
while ((ch = is.read()) != -1)
System.out.print((char) ch);
is.close();
System.out.println("Client program done.");
}
}
3. Use shutdown hooks instead
Don't disallow the termination of the JVM, but instead add shutdown-hooks that cleans up the "hub" and exits gracefully. (This option probably only makes sense if your running one "external" program at a time.)
import java.io.*;
public class Test {
public static void main(String args[]) throws IOException {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Uninitializing hub...");
System.out.println("Exiting gracefully.");
}
});
// Run client program
System.out.println("Running... running... running...");
System.exit(0);
}
}
Prints:
Running... running... running...
Uninitializing hub...
Exiting gracefully.
I'm developing a multi-threaded Java program use different assertions throughout the code and run my program using the ea flag.
Can I make my program immediately stop and exit when any assertion fails?
try {
code that may generate AssertionError
} catch (AssertionError e) {
System.exit(0);//logging or any action
}
enable assertion also.
but it must be taken care.
Assert will stop whatever thread threw the assertion, assuming the AssertionError isn't caught. Although I would think that killing that thread would be enough and you wouldn't want to go and kill the whole program. Anyhow, to actually kill the entire program, just wrap your runnables with a
try {
} catch (AssertionError e) {
System.exit(1);
}
which will kill the program when the assertion is raised.
So you could make a "CrashOnAssertionError" runnable to wrap all of your runnables:
public class CrashOnAssertionError implements Runnable {
private final Runnable mActualRunnable;
public CrashOnAssertionError(Runnable pActualRunnable) {
mActualRunnable = pActualRunnable;
}
public void run() {
try {
mActualRunnable.run();
} catch (AssertionError) {
System.exit(1);
}
}
}
And then you can do something like:
Runnable r = new CrashOnAssertionError(
new Runnable() {
public void run() {
// do stuff
}
});
new Thread(r).start();
When assertions are enabled, they throw a java.lang.AssertionError upon failing. As long as you don't try to catch this, the thread throwing the exception will stop when an assertion fails.
If you want any other behavior, you can catch (AssertionError) and do whatever you want inside the catch statement. For example, call System.exit(1).
If you want AssertionError to include an error message, you need to use the assert Expression1 : Expression2; form of assert. For more information, read this.
There is a console Java application which is supposed to run until it is stopped by Ctrl+C or closing the console window. How that application can be programmed to execute a clean up code before exit?
You could use a Shutdown Hook.
Basically you need to create a Thread which will perform your shutdown actions, and then add it as a shutdown hook. For example:
class ShutdownHook extends Thread
{
public void run()
{
// perform shutdown actions
}
}
// Then, somewhere in your code
Runtime.getRuntime().addShutdownHook(new ShutdownHook())
A Shutdown hook is the way to go, but be aware that there is no guarantee that the code is actually executed. JVM crashes, power failures, or a simple "kill -9" on your JVM can prevent the code from cleaning up. Therefore you must ensure that your program stays in a consistent state even if it has been aborted abruptly.
Personally, I simply use a database for all state-storage. Its transactions model makes sure that the persistent storage is in a sane state no matter what happens. They spend years making that code fool-proof, so why should I waste my time on problems already solved.
Program to delete temp file bat.bat when program is exited:
public class Backup {
public static void createBackup(String s)
{
try{
String fileName ="C:\\bat"+ ".bat";
FileWriter writer=new FileWriter(fileName);
String batquery="cd C:\\Program Files\\MySQL\\MySQL Server 5.0\\bin"
+ "\nmysqldump -uroot -proot bankdb > \""+s+".sql\""
+"\nexit";
writer.append(batquery);
writer.close();
}
catch(Exception e){e.getMessage();}
try{
Process p =Runtime.getRuntime().exec("cmd /c start C:\\bat.bat");
}
catch(Exception e){e.getMessage();}
ShutDownHook sdh=new ShutDownHook();
Runtime.getRuntime().addShutdownHook(sdh);
}
}
class ShutDownHook extends Thread
{
public void run()
{
try
{
File f=new File("c:/bat.bat");
f.delete();
}
catch(Exception e){e.getMessage();}
}
}
The code written inside a Threads run() method will execute when the runtime object terminates...
class ShutdownHookclass extends Thread {
public void run() {
// perform shutdown actions
}
}
//could be written anywhere in your code
Runtime.getRuntime().addShutdownHook(new ShutdownHookclass())