Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am working on a simple java program. It simply compiles and executes another java program. I am using Runtime.exec() function to compile and run. There is no problem with compilation. but when it runs, if the second program needs an input to read from keyboard, I can't give it from the master process. I used getOutputStream() function. but it couldn't help. I will provide my code.

public class sam {  
    public static void main(String[] args) throws Exception {  
        try { 
             Process p = Runtime.getRuntime().exec("javac sam2.java");
             Process p2 = Runtime.getRuntime().exec("java sam2");
             BufferedReader in = new BufferedReader(  
                                new InputStreamReader(p2.getInputStream()));

             OutputStream out = p.getOutputStream();
             String line = null; 
             line = in.readLine();
             System.out.println(line);
             input=input+"\n";
             out.write(input.getBytes());
             p.wait(10000);
             out.flush();
        }catch (IOException e) {  
             e.printStackTrace();  
        }  
    }  
}  

This is my master program(sam.java).

The following is the code of sam2.java

public class sam2 {  
public static void main(String[] args) throws Exception {  

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String str; 
    System.out.println("Enter the number..\n");
    str = br.readLine(); 
    System.out.println(Integer.parseInt(str));

    }  
}  

There is no problem, if my second program has only printing statements. But the problem arises when I have to read something from the other.

share|improve this question
you would have to do some kind of pipe from the STDIN of sam to sam2 but that may be more trouble that its worth. – Alex Gittemeier Mar 5 at 8:22
Please learn java naming conventions and stick to them, here: class names should start with an uppercase letter. – kleopatra Mar 5 at 10:20
i was trying to present a simple example. thanks for your advice.. :) – user2134774 Mar 5 at 12:30

3 Answers

up vote 2 down vote accepted

It is a bit strange but you can run the second program without forking it. Just calling the main method in it. So forget the runtime section and do this:

sam2.main(new String[0]);

Of course this way you must compile sam2 at compile time

share|improve this answer
i couldnt understand what u mean by this statement..!! :( – user2134774 Mar 5 at 12:32
It works.. :) thanks a lot.. But when i use this way.. the entire control will be gone to the second program. so master will execute only after the completion of the second program.. should i use threads to solve this problem..?? – user2134774 Mar 5 at 12:49
Of course you should. – András Tóth Mar 5 at 12:51
Problem..!!! when i store the class name of second program to a string variable it encounters the following error.. cannot find symbol tempfile.main(new String[0]); symbol: method main(String[]) location: variable tempfile of type String What should i do..?? – user2134774 Mar 6 at 4:47
What do you want? You can not use a String as a class instance. Maybe you should use java reflection to this work. But reflection is usually not needed. – András Tóth Mar 7 at 10:01

Each process needs to be allowed to run and finish. You can use Process#waitFor for this purpose. Equally, you need to consume any output from the process at the same time. waitFor will block so you will need use a Thread to read the input (and if you need to, write output to the process)

Depending on the location of the java/class file, you may also need to specify a starting folder from which the execution of the process can start.

Most of this significantly easier using ProcessBuilder

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

public class CompileAndRun {

    public static void main(String[] args) {
        new CompileAndRun();
    }

    public CompileAndRun() {
        try {
            int result = compile("compileandrun/HelloWorld.java");
            System.out.println("javac returned " + result);
            result = run("compileandrun.HelloWorld");
        } catch (IOException | InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    public int run(String clazz) throws IOException, InterruptedException {        
        ProcessBuilder pb = new ProcessBuilder("java", clazz);
        pb.redirectError();
        pb.directory(new File("src"));
        Process p = pb.start();
        InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream());
        consumer.start();

        int result = p.waitFor();

        consumer.join();

        System.out.println(consumer.getOutput());

        return result;
    }

    public int compile(String file) throws IOException, InterruptedException {        
        ProcessBuilder pb = new ProcessBuilder("javac", file);
        pb.redirectError();
        pb.directory(new File("src"));
        Process p = pb.start();
        InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream());
        consumer.start();

        int result = p.waitFor();

        consumer.join();

        System.out.println(consumer.getOutput());

        return result;        
    }

    public class InputStreamConsumer extends Thread {

        private InputStream is;
        private IOException exp;
        private StringBuilder output;

        public InputStreamConsumer(InputStream is) {
            this.is = is;
        }

        @Override
        public void run() {
            int in = -1;
            output = new StringBuilder(64);
            try {
                while ((in = is.read()) != -1) {
                    output.append((char) in);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
                exp = ex;
            }
        }

        public StringBuilder getOutput() {
            return output;
        }

        public IOException getException() {
            return exp;
        }
    }
}

Now obviously, you should check the return results of the processes, and may be produce a better mechanism for interacting with the processes, but that's the basic idea...

share|improve this answer

You can just call the main method of the second class. The main method is just like any other static method.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.