-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I have to use Process proc = Runtime.getRuntime().exec() method to
execute OS level command such as lpr. When I traced Java source code,
Process class's getErrorStream(), getInputStream(), and
getOutputStream() methods are instantiated inside ProcessImpl
constructor. My question is do I have to close all these streams
regardless of using in my program or not to prevent any resource leak?
Source Code:
stdin_stream =
new BufferedOutputStream(new FileOutputStream(stdin_fd));
stdout_stream =
new BufferedInputStream(new FileInputStream(stdout_fd));
stderr_stream =
new FileInputStream(stderr_fd);
Process proc = Runtime.getRuntime().exec( cmdLine.toString() );
InputStream inStrm = proc.getInputStream();
//
...
If ( inStrm != null )
inStrm.close();
Should I call the close() method for stderr_stream and stdout_stream
also even though I don't use it?
Your question is interesting. Below is a simple testing program I
devised to experimentally answer the question.
This program will create a user specified number of processes. The
user can specify whether the program will maintain a hard or soft
reference to the process and whether it will close the streams
associated with the process.
When I asked the program to create 339 processes without closing the
associated streams, the program created 338 processes and crashed on
the 339th. However when I asked the program to create 339 processes
and close the associated streams, the program ran successfully. This
experiment suggests that there is a resource leakage associated with
not closing the process associated streams.
I hope this helps.
Emory Merryman
External Concepts Guild
final class TestLeaking
{
public static final void main ( final java . lang . String [ ]
args ) throws java . lang . Exception
{
final int count = java . lang . Integer . parseInt ( args [ 0 ] ) ;
int i = 0 ;
final boolean strongRef = java . lang . Boolean . parseBoolean ( args
[ 1 ] ) ;
final boolean weakRef = java . lang . Boolean . parseBoolean ( args
[ 2 ] ) ;
final boolean closeInputStream = java . lang . Boolean . parseBoolean
( args [ 3 ] ) ;
final boolean closeOutputStream = java . lang . Boolean .
parseBoolean ( args [ 4 ] ) ;
final boolean closeErrorStream = java . lang . Boolean . parseBoolean
( args [ 5 ] ) ;
final long start = new java . util . Date ( ) . getTime ( ) ;
final java . lang . Runtime runtime = java . lang . Runtime .
getRuntime ( ) ;
try
{
for ( i = 0 ; i < count ; i ++ )
{
process ( runtime , strongRef , weakRef , closeInputStream ,
closeOutputStream , closeErrorStream ) ;
}
}
finally
{
final long stop = new java . util . Date ( ) . getTime ( ) ;
final int k = processes . size ( ) ;
final long elapsed = stop - start ;
java . lang . System . out . println ( i + "\t" + count + "\t" +
strongRef + "\t" + weakRef + "\t" + closeInputStream + "\t" +
closeOutputStream + "\t" + closeErrorStream + "\t" + start + "\t" +
stop + "\t" + elapsed + "\t" + k ) ;
}
}
private static java . util . List < java . lang . Process >
processes = new java . util . ArrayList < java . lang . Process >
( ) ;
public static final void process ( final java . lang . Runtime
runtime , final boolean strongRef , final boolean weakRef , final
boolean closeInputStream , final boolean closeOutputStream , final
boolean closeErrorStream ) throws java . io . IOException
{
final java . lang . Process process = runtime . exec ( "ls" ) ;
if ( strongRef )
{
processes . add ( process ) ;
}
if ( weakRef )
{
waitForGC ( process ) ;
}
if ( closeInputStream )
{
final java . io . InputStream stream = process . getInputStream
( ) ;
stream . close ( ) ;
}
if ( closeOutputStream )
{
final java . io . OutputStream stream = process . getOutputStream
( ) ;
stream . close ( ) ;
}
if ( closeErrorStream )
{
final java . io . InputStream stream = process . getErrorStream
( ) ;
stream . close ( ) ;
}
}
public static final void waitForGC ( final java . lang . Process
process )
{
final java . lang . ref . Reference < java . lang . Process > ref =
new java . lang . ref . WeakReference < java . lang . Process >
( process ) ;
final java . lang . Runnable runnable = new java . lang . Runnable
( )
{
public final void run ( )
{
while ( ref . get ( ) != null )
{
}
}
} ;
final java . lang . Thread thread = new java . lang . Thread
( runnable ) ;
thread . start ( ) ;
}}
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
iD8DBQFHZzLrVQdj5Q2e9q0RAlbDAJ47FPFrQg0aOWOSCcU2cPEQ5z/4GwCff075
+rnog+D+PCh+bl1l18ZRnF0=
=hVhr
-----END PGP SIGNATURE------ Hide quoted text -
- Show quoted text -