1

I'm writing a program that executes another Java program by using the Class and Method classes to invoke the main method. This other program then tries to read from System.in. In order to pass arguments to the program, I set System.in to a PipedInputStream that is connected to a PipedOutputStream. I pass the arguments the other program requests to the PipedOutputStream, then invoke the main method.
However, as soon as the method is invoked, the program deadlocks. Why is that? Theoretically, the other program should have access to the arguments, since they're already available in the PipedInputStream.
I can't change the way the other program reads the input, so this solution wouldn't work.

Here some example code:
The part where I assign the PipedStreams

PipedInputStream inputStream = new PipedInputStream();
PipedStringOutputStream stringStream = new PipedStringOutputStream(); // custom class

try {
    stringStream.connect(inputStream);
} catch (IOException e2) {
    e2.printStackTrace();
}
System.setIn(inputStream);

The part where I invoke the method:

Class main = classes.get(className);
try {
    Method m = main.getMethod("main", String[].class);

    // write all parameters to System.in
    String[] params = getParams(); // custom method, works (params is not empty)
    for(int j = 0; j < params.length; j++) {
       stringStream.write(params[j]);
    }

    params = null;
    m.invoke(null, (Object) params); // this is were the program stops
} catch(Exception e) {}

The PipedStringOutputStream class:

public class PipedStringOutputStream extends PipedOutputStream {

    public void write(String output) throws IOException {
        this.write((output + "\n").getBytes());
        flush();
    }
}

My test program that reads from System.in:

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    while(sc.hasNext()) {
        System.out.println(sc.nextLine());
    }
}

So what is the problem? Do I have to start the Streams in Threads? Why doesn't the other program read the input from the PipedInputStream?

3
  • 1
    (1) There's no code here that reads from anything, let alone the pipe. (2) As you are already passing the arguments to main() directly, why the pipe? (3) What's the question here? Commented Jul 27, 2013 at 12:24
  • What your main method is doing? Show its code too. Commented Jul 27, 2013 at 12:52
  • @EJP: 1) I added some example code that reads from System.in 2) I'm not passing the arguments to main() directly, params is null at this point. The other programm will read from System.in, so I have to pass the arguments that way. 3) The question is how I can pass the arguments to the System.in so that the other program can read them. Assuming the pipes are the right step, I want to know what's wrong in my code. Commented Jul 28, 2013 at 16:06

1 Answer 1

2

The javadoc of PipedInputStream explicitely says:

Typically, data is read from a PipedInputStream object by one thread and data is written to the corresponding PipedOutputStream by some other thread. Attempting to use both objects from a single thread is not recommended, as it may deadlock the thread.

(emphasis mine)

Write your input to a byte array using a ByteArrayOutputStream. Then construct a ByteArrayInputStream from this byte array, and set System.in to this ByteArrayInputStream.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! This works fine if i call the other program's main method as a normal method call, but when I call it via invoke() it doesn't seem to be able to read from the ByteArrayInputStream, even though the correct bytes are there to be read. The Scanner's hasNext() method always returns false. Why could this be?
Invoking the method directly of using reflection shouldn't change anything. Use hashNextLine() to test if there's a next line. Not hasNext().
Now it works. I had a little struggle with Java's call-by-value system, which is why System.in wasn't set to the right stream.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.