Reputation: 4547
I have created a Java application that has 2 Jar files. Jar1 is used to initialize and run Jar2, using this code :
Process process = runtime.exec( "java -jar Jar2.jar" );
printLogs( process );
.
.
.
private static boolean printLogs( Process process ) {
try {
BufferedInputStream logStream = new BufferedInputStream( process.getInputStream() );
String logs = "";
int buffer = 0;
while ( ( buffer = logStream.read() ) != -1 ) {
logs += (char)buffer;
}
if( !logs.isEmpty() ) logger.debug( logs );
} catch (IOException e) {}
return true;
}
I print many logs from Jar2 using Log4J, i.e.
logger.debug( "..." );
But none of the logs in Jar2 were printed to the console. I figured out it's because the logs are returned to Jar1 and not to the console, So i printed the returning stream using the above code. Logs are now printed fine but after all Jar2 process ends up, then all logs are printed at once in Jar1.
The question is: Can i print each log line in Jar2 in time instead of waiting all Jar2 process to end ?
Because Jar2 is a long process, and it is important that i can see those logs while the application is processing.
Upvotes: 0
Views: 1677
Reputation: 4547
With the help of this post i was able to fix this :
Runtime.exec never returns when reading system.in
I have used the ProcessBuilder too.
Upvotes: 0
Reputation: 20885
The whole thing is quite messed up. You shouldn't need two separate archives and Runtime.exec()
However, one usually uses BufferedReader.readLines
to read text lines. Note that the problem simply vanishes if you log each line at the moment you read it:
BufferedReader input = new BufferedReader(
new InputStreamReader(process.getInputStream())
);
String line = null;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
Your code waits to the child process to complete because you logged the line after the stream ends (ie after the subprocess has terminated)
Here is a demo program which uses a long running Ruby program as the watched process
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Subprocess {
static final String[] program = new String[] {
"ruby",
"-e" ,
"(1..5).each{|i|sleep 1;puts i;STDOUT.flush}"
};
public static void main(String[] args) throws IOException {
ProcessBuilder builder = new ProcessBuilder(program);
builder.redirectErrorStream();
Process child = builder.start();
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(child.getInputStream()));
while ((line = in.readLine()) != null)
System.out.println(line);
}
}
Upvotes: 2
Reputation: 483
Your code seems to be waiting for the logStream
to get to EOF
before actually writing logs (which occurs when the process exits). Try refactoring it to read it character-by-character, then logging the accumulated character buffer whenever you see a newline (and EOF
, of course - so you get the last line).
Upvotes: 0