I want compile Java program by making a Javac command in cmd using another Java program, then run it. How do I do that? Is there a class that i can use?
for example here is the cmd
C:\Users\UserName\Documents> Javac HelloWorld.java
How can i compile HelloWorld.java inside a java program, then run it.
Here is my initial source code wherein there is a directory and a Java file.
public class Test {
public static void main(String[] args) {
String directory = "C:\\Users\\UserName\\Documents";
String fileName = "HelloWorld.java";
}
}
Try this
try {
// Execute command
String command = "cmd /c start cmd.exe";
Process child = Runtime.getRuntime().exec(command);
// Get output stream to write from it
OutputStream out = child.getOutputStream();
out.write("<execute the java class by mentioning the usual command>");
out.flush();
out.close();
} catch (IOException e) {
}
You probably want to compile the other source code first. The Java compiler is actually written in Java itself. You do not need to invoke the javac.exe, instead take a look at javax.tools.ToolProvider.getSystemJavaCompiler() ToolProvider Javadoc.
Once you compiled the source code file with that, you can use the class loader to load the compiler class file and invoke the code from there, probably by means of reflection.
Overall you are asking for an advanced use case.
if you want to compile different java files using this a program , you can try this method.
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
try {
runProcess("javac YourDir/HelloWorld.java");
runProcess("java YourDir.HelloWorld");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class HelloWorld {
public static void main(String[] args) {
System.out.println("ok");
}
}
Related
(Sorry for my english I'm french) I'm creating a tiny Java IDE for my school project, but I'm facing a problem with running classes under Linux (I'm using Debian 7.3), no problem with Win 8.1
I'm using ProcessBuilder class to execute the java bin with some arguments, wich are args and projectOut
args = the class we want to run
projectOut = the absolute project path+"/out"
package com.esgi.honeycode;
import java.io.*;
import java.util.Scanner;
public class CustomRun {
public static void run(String args, final String projectOut) throws IOException {
System.out.flush();
if (args != null && projectOut != null) {
//SEPARATOR is a const for the file separator
ProcessBuilder builder = new ProcessBuilder("java", "-classpath", "\"" + System.getProperty("java.class.path") + System.getProperty("path.separator") + projectOut + PropertiesShared.SEPARATOR + "out\"", args);
System.out.println(builder.command());
builder.redirectErrorStream(true);
final Process process = builder.start();
Thread outThread = new Thread()
{
#Override
public void run() {
try {
String line;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
};
Thread inThread = new Thread() {
#Override
public void run() {
Scanner s = new Scanner(System.in);
//Need to control in before !!
while (true) {
String input = s.nextLine();
try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(process.getOutputStream()))) {
pw.write(input);
pw.flush();
}
}
}
};
outThread.start();
inThread.start();
}
}
}
Testing with a simple class :
public class MyClass{
public static void main(String[] args)
{
System.out.println("TESTESTE");
}
}
the class is stored in : /home/m3te0r/HoneyCodeProjects/untitledaaa/out
And if I try to run the class, I get this output, with the command print :
[java, -classpath, "/home/m3te0r/Bureau/HoneyCode.jar:/home/m3te0r/HoneyCodeProjects/untitledaaa/out", MyClass]
Error: Could not find or load main class MyClass
Like I said, there is no problem under Win 8.1 and it also works when I run the same command in a terminal.
EDIT FOR THE ANSWER ():
Ok, so I figured out what was wrong.
I just removed the escaped double quotes fot the classpath and it worked.
I was thinking there would be a problem with spaced dir names or files, but there is not.
ProcessBuilder builder = new ProcessBuilder("java", "-classpath", System.getProperty("java.class.path") + System.getProperty("path.separator") + projectOut + PropertiesShared.SEPARATOR + "out", args);
Alright, i'm trying to Xbootclasspath a jar from within my project. Currently I have to load my application through command-line with the follow command:
java -Xbootclasspath/p:canvas.jar -jar application.jar
This works perfectly fine but I want to do this without having to enter command line, is there I way I can Xbootclasspath from within the jar?
Thanks.
The most clear solution is to have two main classes.
Your first class, named Boot or similar, will be the outside entry point into the application, as set in the jar's manifest. This class will form the necessary runtime command to start your actual main class (named Application or similar), with the Xboot parameter.
public class Boot {
public static void main(String[] args) {
String location = Boot.class.getProtectionDomain().getCodeSource().getLocation().getPath();
location = URLDecoder.decode(location, "UTF-8").replaceAll("\\\\", "/");
String app = Application.class.getCanonicalName();
String flags = "-Xbootclasspath/p:canvas.jar";
boolean windows = System.getProperty("os.name").contains("Win");
StringBuilder command = new StringBuilder(64);
if (windows) {
command.append("javaw");
} else {
command.append("java");
}
command.append(' ').append(flags).append(' ');
command.append('"').append(location).append('"');
// append any necessary external libraries here
for (String arg : args) {
command.append(' ').append('"').append(arg).append('"');
}
Process application = null;
Runtime runtime = Runtime.getRuntime();
if (windows) {
application = runtime.exec(command.toString());
} else {
application = runtime.exec(new String[]{ "/bin/sh", "-c", command.toString() });
}
// wire command line output to Boot to output it correctly
BufferedReader strerr = new BufferedReader(new InputStreamReader(application.getErrorStream()));
BufferedReader strin = new BufferedReader(new InputStreamReader(application.getInputStream()));
while (isRunning(application)) {
String err = null;
while ((err = strerr.readLine()) != null) {
System.err.println(err);
}
String in = null;
while ((in = strin.readLine()) != null) {
System.out.println(in);
}
try {
Thread.sleep(50);
} catch (InterruptedException ignored) {
}
}
}
private static boolean isRunning(Process process) {
try {
process.exitValue();
} catch (IllegalThreadStateException e) {
return true;
}
return false;
}
}
And your Application class runs your actual program:
public class Application {
public static void main(String[] args) {
// display user-interface, etc
}
}
Feels yucky, but could you do a Runtime.exec that calls to java with the provided options and a new parameter (along with some conditional code that looks for that) to prevent a recursive loop of spawning new processes?
I have a Main.java and Test.java classes that I want to compile and run Main.java in Test.java code. Here is my code
Process pro1 = Runtime.getRuntime().exec("javac Main.java");
pro1.waitFor();
Process pro2 = Runtime.getRuntime().exec("java Main");
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
I just print "ok" in Main.java but this code doesn't print anything. What is the problem ?
I have modified the code to include some checks:
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
try {
runProcess("javac Main.java");
runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the Main.java:
public class Main {
public static void main(String[] args) {
System.out.println("ok");
}
}
When everything is fine, it just works:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java exitValue() 0
java Main stdout: ok
java Main exitValue() 0
Now, for example, if I have some error in Main.java:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java stderr: Main.java:3: package Systems does not exist
javac Main.java stderr: Systems.out.println("ok");
javac Main.java stderr: ^
javac Main.java stderr: 1 error
javac Main.java exitValue() 1
java Main stdout: ok
java Main exitValue() 0
It still prints "ok" because the previously compiled Main.class is still there, but at least you can see what exactly is happening when your processes are running.
You also need to
pro2.waitFor();
because executing that process will take some time and you can't take the exitValue() before the process has finished.
I have added the condition in Laj class main function to check for compilation process has completed successfully or not..
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static int runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
// System.out.println(command + " exitValue() " + pro.exitValue());
return pro.exitValue();
}
public static void main(String[] args) {
try {
int k = runProcess("javac Main.java");
if (k==0)
k=runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}
I'm trying to execute terminal command in linux trough Java and i cant get any input from inputStream.
This is my code
ProcessBuilder build = new ProcessBuilder("/usr/bin/xterm", "find /home");
Process pr = null;
BufferedReader buf;
try {
build.redirectErrorStream(true);
pr = build.start();
buf = new BufferedReader(new InputStreamReader( pr.getInputStream()));
String line = buf.readLine();
pr.waitFor();
while (true) {
System.out.println(line + "sadasdas");
line = buf.readLine();
}
} catch (Exception e) {
e.printStackTrace();
}
Process is executed and immediately terminal closes, and no output is catched and printed. On the other hand if i will compose an unknown command i get all the lines with tips how to use commands. Same problem i had with windows cmd. I was trying to use getRuntime.exec(cmd) method but the end is the same.
I've also tried to created separate threads for process and reader which looks like this
public class kurdee
{
public static Thread thread;
public kurdee()
{
List cmd = new LinkedList();
cmd.add(new String("/usr/bin/xterm"));
cmd.add(new String("find"));
thisProc thispr = new thisProc(cmd);
this.thread = new Thread(thispr);
thread.start();
reader rd = new reader(thispr.proc);
Thread thread1 = new Thread(rd);
thread1.start();}
public static void main(String args[])
{
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
kurdee kurd = new kurdee();
}
});
}
}
class reader implements Runnable
{
private BufferedReader buf;
private Process proc;
public reader(Process proc)
{
this.proc=proc;
this.buf = new BufferedReader(new InputStreamReader(proc.getInputStream()));
}
public void run()
{
String line="";
System.out.println("Thread is alive");
try{
//Thread.sleep(1000);
line = buf.readLine();
}catch(Exception ex){System.out.println(ex + " before first while started");}
while(kurdee.thread.isAlive())
{
System.out.println("Thread is alive");
while(line!=null)
{
try{
//System.out.println(proc.exitValue());
System.out.println(line + " asd");
line=buf.readLine();
}catch(Exception e){System.out.println(e + " Inner while loop");}
}
}
}
}
class thisProc implements Runnable
{
private ProcessBuilder build;
public static Process proc=null;
public thisProc(List<String> args)
{
this.build = new ProcessBuilder(args);
build.redirectErrorStream(true);
try{
this.proc = build.start();
}catch(Exception ex){System.out.println(ex + " proc class");}
}
public void run()
{
try{
proc.waitFor();
}catch(Exception ex){System.out.println(ex + " proc class");}
}
}
But with any combination of invoking threads etc i make there is still nothing to read.
I'm trying to use command "find /home -xdev -samefile file" to get all hard links to file so maybe there is an easier way.
xterm is not the way to execute processes in unix, it is not a shell. a shell is something like "/bin/sh". however, "find" is a normal unix executable, so you should just execute that directly, e.g. new ProcessBuilder("find", "/home"). and yes, you should always process the streams on separate threads, as recommended by this article.
First, don't try to execute the command with xterm, that's pointless; just do it directly. Secondly, be careful when you compose your array of command strings to put one word into each string; passing, for example "find /home" as a single string among many to ProcessBuilder is going to error out.
I have a Main.java and Test.java classes that I want to compile and run Main.java in Test.java code. Here is my code
Process pro1 = Runtime.getRuntime().exec("javac Main.java");
pro1.waitFor();
Process pro2 = Runtime.getRuntime().exec("java Main");
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
I just print "ok" in Main.java but this code doesn't print anything. What is the problem ?
I have modified the code to include some checks:
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
try {
runProcess("javac Main.java");
runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the Main.java:
public class Main {
public static void main(String[] args) {
System.out.println("ok");
}
}
When everything is fine, it just works:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java exitValue() 0
java Main stdout: ok
java Main exitValue() 0
Now, for example, if I have some error in Main.java:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java stderr: Main.java:3: package Systems does not exist
javac Main.java stderr: Systems.out.println("ok");
javac Main.java stderr: ^
javac Main.java stderr: 1 error
javac Main.java exitValue() 1
java Main stdout: ok
java Main exitValue() 0
It still prints "ok" because the previously compiled Main.class is still there, but at least you can see what exactly is happening when your processes are running.
You also need to
pro2.waitFor();
because executing that process will take some time and you can't take the exitValue() before the process has finished.
I have added the condition in Laj class main function to check for compilation process has completed successfully or not..
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static int runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
// System.out.println(command + " exitValue() " + pro.exitValue());
return pro.exitValue();
}
public static void main(String[] args) {
try {
int k = runProcess("javac Main.java");
if (k==0)
k=runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}