 |
AppletTalk.com Java discussions newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Guest
|
Posted: Fri Jan 19, 2007 3:18 pm Post subject: Out of memory with IBM's JDK Process implementation (possibl |
|
|
Hi,
The problem I'm describing is concerned with forking child process from
the JVM and out-of-memory due to communication with it.
The problem is concerned with IBM's JVM Process class implementation.
| Quote: | From the
tests performed it seems the Process class consumes the data written on |
the child's stdout even we don't do it explicitly, i.e.
Process.getInputStream().read(). In this case the data is buffered in
vector with byte array reference elements. It also seems that there's
no
limit for the number of elements in the vector, because the child
writes
till JVM out of memory crash.
With SUN's JVM the writer (forked process) blocks until the reader
(Java Process) reads the data from the pipe, which is the
normal IPC based on pipes.
The test consists of two programs:
- symb.c, which infinitely writes data to its STDOUT and registers the
number of writes done in symb.out file
- ProcessTest.java, which forks "symb" executable and only checks (and
prints on stdout) the number of bytes available on its InputStream
(symb's stdout).
With SUN's JVM the Java program shows that the number of available
bytes
is constant and in symb.out we have only one entry, i.e. only one write
is performed. With IBM's JVM the number of available bytes increases
till the JVM crash (the writer doesn't block). In the dump file we see
vector with references to bytes arrays: ProcessPipedInputStream
-> Vector -> array of byte with unlimited count.
Obviously the reader (java thread using Process) is slower than the
writer (forked C process) and a lot of data is buffered into the
endless Vector, which is the source of the random crashes with
out-of-memory.
I think that this is a bug in IBM's implementation. For now I don't
know is there any workaround for this. It'll be best if
there is some property (IBM specific) that specifiess the Array length
or s'thing similar.
Any comments and ideas are appreciated.
Regards,
Krasimir Vanev
Here are the test programs:
------------------------------symb.c----------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include <dirent.h>
#include <signal.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/resource.h>
#define FILE_MODE (mode_t)(S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR)
main()
{
/*the data*/
char buffer[65535];
/*for logging*/
char message[1024];
/*redirect stderr to "symb.out" for logging*/
int fd = open("symb.out", O_WRONLY|O_APPEND|O_CREAT, FILE_MODE);
if (fd >= 0 && fd != STDERR_FILENO) {
dup2(fd, STDERR_FILENO);
close(fd);
}
for(; {
if(fwrite(buffer, 65535, 1, stdout) != 1) {
// error
snprintf(message, 1023, "couldn't write to STDOUT\n");
fwrite(message, strlen(message), 1, stderr);
}
snprintf(message, 1023, "written to STDOUT: 65535\n");
fwrite(message, strlen(message), 1, stderr);
fflush(stdout);
fflush(stderr);
}
}
------------------------------------------------------------------------------------------------------------------------------
-------------------------ProcessTest.java----------------------------------------------------------------------------
import java.io.BufferedInputStream;
public class ProcessTest {
public Process getProcess() {
Process process = null;
try {
// Hardcoded executable - "symb" from the current directory
process = Runtime.getRuntime().exec(new
String[] {"./symb"});
// We won't use err and out streams
process.getErrorStream().close();
process.getOutputStream().close();
return process;
} catch (Exception e) {
System.err.println("getProcess() exception:" +
e.toString());
if (process != null) {
process.destroy();
}
}
return process;
}
public static void main(String[] args) {
try {
ProcessTest test = new ProcessTest();
Process symb = test.getProcess();
BufferedInputStream symbIS = new
BufferedInputStream(symb.getInputStream());
int available = 0;
//give the child enough time to fill in the buffer
Thread.currentThread().sleep(1000);
while((available = symbIS.available()) > 0) {
System.out.println("Available to read:
" + available);
}
System.err.println("Exitting...available = " +
available);
} catch (Exception e) {
System.err.println("main() exception: " + e.toString());
}
}
}
------------------------------------------------------------------------------------------------------------------------ |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|