I need to compile and run source code (single file), written in Python, Pascal or C, from my Java application.
I will need to know:
if compile process was successful
the return output of the compiled program
How could I accomplish that?
I have been doing the same thing..
public String compile()
{
String log="";
try {
String s= null;
//change this string to your compilers location
Process p = Runtime.getRuntime().exec("cmd /C \"C:\\Program Files\\CodeBlocks\\MinGW\\bin\\mingw32-g++.exe\" temp.cpp ");
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
boolean error=false;
log+="\n....\n";
while ((s = stdError.readLine()) != null) {
log+=s;
error=true;
log+="\n";
}
if(error==false) log+="Compilation successful !!!";
} catch (IOException e) {
e.printStackTrace();
}
return log;
}
public int runProgram()
{
int ret = -1;
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("cmd.exe /c start a.exe");
proc.waitFor();
ret = proc.exitValue();
} catch (Throwable t)
{
t.printStackTrace();
return ret;
}
return ret;
}
This are 2 functions used in my MiDE first one used to compile. Change the address to your compilers location. and returns the log(in case compilation was failed) to see the errors.
The 2nd one runs the compiled code. Returning the exit code to check whether it terminated correctly.
I am not a very good java coder . i guess you can improve my code a lot better ;) .. in case you do please inform me. And i am also looking for a answer on how to communicate with the created process
You could use java.lang.ProcessBuilder to execute commands and check the status.
Here JAVADOC : http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ProcessBuilder.html
In general, you'll want to launch a Process that runs the external program (first the compiler, and then the compiled binary in your case), using either Runtime.getRuntime().exec() or a ProcessBuilder to spawn the Process (since your compiler probably takes a complicated set of options, the ProcessBuilder is likely a better option). This will allow you to grab the output from the process as it executes (so you can monitor the compiler output for warnings or errors), as well as its return code.
You may find the following examples helpful:
http://www.rgagnon.com/javadetails/java-0014.html
To get the return code of a running Process, just use the waitFor() method. This is convenient if you don't care about any of the output and just want the return value.
You're probably going to want to use Runtime.exec() to call the respective compiler. Check out the JavaDoc for more information about how to deal with the output, etc.
If you're mainly doing code snippets you might try running Python code using Jython. See Howto multithreaded jython scripts running from java? for details.
Related
I am using Runtime.getRuntime().exec function to launch independent GUI Java application for subroutine task.
The code used is in simple manner:
Runtime.getRuntime().exec("java -jar /home/user/jar.jar");
Executing the code doesn't cause any process launch nor error occured! ProcessBuilder has same effect.
Checked to work correctly on Windows.
As seems, on some platforms it is ignored on system level outside Java, as JRE does not return any kind of error.
EDT: I edited the code to read stderr and stdout by parallel thread to preserve main app execution:
Process p = Runtime.getRuntime().exec(runCmd);
new DaemonFailPrint(p).start();
Thread code is:
public class DaemonFailPrint extends Thread {
private Process process;
public DaemonFailPrint(Process process) {
this.process = process;
}
#Override
public void run() {
try {
process.waitFor();
String out = "";
while (process.getInputStream().available() > 0) {
out += (char) process.getInputStream().read();
}
out += System.lineSeparator();
while (process.getInputStream().available() > 0) {
out += (char) process.getErrorStream().read();
}
JOptionPane.showMessageDialog(null, out);
} catch (InterruptedException | IOException ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
}
The result is: I got empty message box straight after subprocess is "launched".
The mean is Process object seems to be created and finished in same time, but no error out exists.
The Runtime::exec() does not wait for the process to exit, so if you want to detect errors in the executed program itself, you'd need to use something like:
Process process = Runtime.getRuntime().exec("java -jar /home/user/jar.jar");
int rc = process.waitFor();
if (rc != 0)
{
System.err.println("The process failed with error: " + rc);
}
It might be, that the jar is not found or cannot be executed etc., those errors you normally see on the console, but if you have no console, the only clue might be the return code.
You might also want to check here how to capture the output console:
Capturing stdout when calling Runtime.exec
Seems that you can use process.getInputStream() to connect to the output stream of the process. So you can simply copy it to the console to see what happened.
So far so good! I found the answer recently by myself, still don't have a reason why it works this way, but I suppose it's all about internal difference of handling new processes in VM's on different platforms.
I had to edit the code this way, and now it works:
String[] runcmd = {"java","-jar","/home/user/jar.jar"};
Runtime.getRuntime().exec(runcmd);
Now it seems to work perfect. As I see it fails to process the file and execute then command with parameters given as same string while no error thrown on Java code level, it's possibly lost in VM internals.
I have a Java program (in jar) which will invoke a batch file by passing parameters. The same batch file will be invoked 10 times with different values passing through parameter.
Which means the batch will be running in parallel with 10 instances.
The issue here is, all the process getting stopped at some point without any reason.
Please advise how to fix it.
public static void run(String batpath)
{
try
{
System.out.println("Call a batch file");
Process p= Runtime.getRuntime().exec("cmd /c CD D:\\ && cd "+v_Base_Path+" && "+batpath+" ");
p.waitFor();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
Naturally, the first thing to check is whether your command cmd /C CD ... works correctly outside of Java.
Then, the recommended way to launch subprocesses is with ProcessBuilder:
The following is for Java 7 (see this answer for a Java 6 solution).
public class Processes
{
public static void main(String... args)
{
for (int i = 0; i < 10; i++)
{
try
{
System.out.println("Call a batch file " + i);
new ProcessBuilder("cmd", "/C", "echo", "hello").inheritIO().start();
//new ProcessBuilder("bad", "/C", "echo", "hello").inheritIO().start();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
}
This enables you to print out the standard output and error streams, so you can see any output from your batch files. Without this, you won't see any clue as to what is wrong with the subprocesses.
If you use the commented-out "bad" line above instead of the "good" line, then you should see errors instead of "hello"s.
(If your batch files don't produce any output or error text, or are hanging forever, then there's nothing you can do at the Java level to debug and fix them - you have to look at them directly to find out why they are not working).
Your batch files may actually be hanging because you are not reading the output streams, as mentioned in the Process documentation:
Because some native platforms only provide limited buffer size for
standard input and output streams, failure to promptly write the input
stream or read the output stream of the subprocess may cause the
subprocess to block, or even deadlock.
See the excellent (though now somewhat out-of-date now that Java 7 and 8 are out) When Runtime.exec() won't article for a detailed discussion.
I tried out a simple program to execute Linux command at run time. But the following program gets compiled and runs without any error, but the text file is not getting created as intended.Is there anything wrong in this program?
import java.io.*;
class ExecuteJava
{
public static void main(String args[])
{
String historycmd = "cat ~/.bash_history >> Documents/history.txt";
try
{
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(historycmd);
}
catch(Exception e)
{
System.out.println(e);
}
}
}
Try accessing some of the functions Process provides. I'd start with exitValue. Typically a -1 indicates something went wrong while a 0 means nothing especially bad happened.
Also try InputStream and Error Stream, and read them fully. See if either has useful feedback for you.
Other than that, try what andy256 suggests in comments. Ensure the Documents directory exists in the executing directory of the program.
The append operator >> is meant to be interpreted as part of the command shell. Use
String[] historycmd =
{ "bash", "-c", "cat ~/.bash_history >> Documents/history.txt"};
I am building a Java application that calls a system command and executes that command before returning control to the Java thread. The debugging step that I have is that I have made a perl script called test.pl and I call that script from the Java method and in Windows I get the expected output and a return value of 0. In Linux I get no output or error output and I get a return value of 136. I have spent extensive time online trying to figure out where I have gone wrong but as I have said, on Windows it runs. I think it must be a simple error that I am just not catching.
Here is the code derived from the excellent Runtime.exec() tutorial at http://www.javaworld.com/jw-12-2000/jw-1229-traps.html
try {
FileOutputStream fos = new FileOutputStream("output/" + this.startPosition + ".txt");
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(new String[]{"perl", "/data/stat-positive-selection/thaddeus/treesim/chr2YRI/test.pl"});
//System.out.println(commandLine);
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");
// any output?
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT", fos);
// kick them off
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
fos.flush();
fos.close();
} catch (Throwable e){
e.printStackTrace();
}
}
I have figured it out and fixed the code
new exec call, the use of the shell and the path to perl are required
Process proc = rt.exec(new String[]{"/bin/bash", "-c", "/usr/bin/perl /data/stat-positive-selection/thaddeus/treesim/chr2YRI/test.pl"});
The differences between the old and new versions are:
you are running the command from a shell, and
you are specifying the full pathname of the "perl" command.
In fact, in this context there doesn't seem to be a great deal of point in running the command from a shell. (Hypothetically, your Perl application might depend on environment variables that are set during shell initialization. However, the same environment variables would normally be inherited by and then from the Java command's environment. So unless the Java command is being launched in a strange way, this scenario is ... unlikely.)
So I think the substantative difference1 is that you are using the full pathname for "perl" ... and you don't a subshell to do that.
So, in the interests of science ( :-) ) I suggest you try this:
Process proc = rt.exec(new String[]{
"/usr/bin/perl",
"/data/stat-positive-selection/thaddeus/treesim/chr2YRI/test.pl"});
1 - ... the difference that makes a difference
I replaced the whole Runtime.exec() structure with the Apache Commons Exec library. It fixed the problem I was having.
http://commons.apache.org/proper/commons-exec/tutorial.html
What is the simplest way to call a program from with a piece of Java code? (The program I want to run is aiSee and it can be run from command line or from Windows GUI; and I am on Vista but the code will also be run on Linux systems).
Take a look at Process and Runtime classes. Keep in mind that what you are trying to accomplish is probably not platform independent.
Here is a little piece of code that might be helpful:
public class YourClass
{
public static void main(String args[])
throws Exception
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("name_of_your_application.exe");
int exitVal = proc.exitValue();
System.out.println("Process exitValue: " + exitVal);
}
}
One question in S.O. discussing similiar issues. Another one. And another one.
You can get a runtime instance using Runtime.getRuntime() and call the runtime's exec method, with the command to execute the program as an argument.
For example:
Runtime runTime = Runtime.getRuntime ();
Process proc = rt.exec("iSee.exe");
You can also capture the output of the program by using getting the InputStream from the process.
The difficulty you will run into is how to get the application to know the path. You may want to use an xml or config file, but if you use this link, it should explain how to run a file:
http://www.javacoffeebreak.com/faq/faq0030.html
You may also want to consider passing in some kind of argument to your program to facilitate finding the specific program you want to run.
This could be with command line arguments, properties files or system properties.