Download (direct link):
int exitVal = proc.waitFor();
Since the argument to Runtime.exec() is operating system-dependent, the proper commands to use will vary from one operating system to another. So, before finalizing arguments to Runtime.exec(), it would be valuable to be able to quickly test the arguments before writing the code. Listing 1.7 is a simple command-line utility to allow you to do just that.
01: package org.javapitfalls.item1;
03: import java.util.*;
04: import java.io.*;
Listing 1.7 TestExec.java (continued)
16 Item 1
// Class StreamGobbler omitted for brevity
33 public class TestExec
35 public static void main(String args)
// argument check omitted for brevity
45 String cmd = args;
46 Runtime rt = Runtime.getRuntime();
47 Process proc = rt.exec(cmd);
48 // remaining code
Identical to GoodWindowsExec.java
Listing 1.7 (continued)
Running TestExec to launch the Netscape browser and load the Java help documentation produces:
E:\classes\org\javapitfalls\item1>java org.javapitfalls.iteml.TestExec ^ "e:\java\docs\index.html"
java.io.IOException: CreateProcess: e:\java\docs\index.html error=193 at java.lang.Win32Process.create(Native Method) at java.lang.Win32Process.<init>(Unknown Source) at java.lang.Runtime.execInternal(Native Method) at TestExec.main(TestExec.java:45)
So, our first test failed with an error of 193. The Win32 Error for value 193 is "not a valid Win32 application." This tells us that there is no path to an associated application (like Netscape) and the process cannot run an HTML file without an associated application. So, we can try the test again, this time giving it a full path to Netscape (or we could have added Netscape to our PATH environment variable). A second run of TestExec produces:
E:\classes\com\javaworld\jpitfalls\article2>java TestExec ^
"e:\program files\netscape\program\netscape.exe e:\java\docs\index.html" ExitValue: 0
This worked! The Netscape browser was launched, and it then loaded the Java help documentation.
NIO Performance and Pitfalls 17
One useful exercise would be to modify TestExec to redirect the standard input or standard output to a file. When you are executing the javac compiler on Windows 95 or Windows 98, this would solve the problem of error messages scrolling off the top of the limited command-line buffer. Here are the key lines of code to capture the standard output and standard error to a file:
FileOutputStream err = new FileOutputStream("stderror.txt");
FileOutputStream out = new FileOutputStream("stdout.txt");
Process proc = Runtime.getRuntime().exec(args);
// any error message?
= new StreamGobbler(proc.getErrorStream(), "ERR", err);
// any output?
= new StreamGobbler(proc.getInputStream(), "OUT", out);
One other improvement to TestExec would be a command-line switch to accept input from standard-in. This input would then be passed to the spawned external program using the Process.getOutputStream() method. This pitfall has explored several problems in using the Runtime.exec() method and supplied workarounds to assist you in executing external applications.
Item 2: NIO Performance and Pitfalls
The NIO packages represent a step forward for input/output (IO) performance and new features; however, these enhancements do not come without some cost in complexity and potential pitfalls. In this item, we examine some of the benefits and deficiencies in this new package. Before we examine specific features, let's get a high-level view of the package and its features. There are four major abstractions in the NIO packages:
Channels. A channel represents a connection to entities capable of performing IO operations like files and sockets. Thus, channels are characterized by the thing they are connected to like FileChannel or SocketChannel. For fast IO, channels work in conjunction with buffers to read from the source or write to the sink. There are also interfaces for different roles a channel can play like Gath-eringByteChannel or ScatteringByteChannel, which can write or read from multiple sequences of buffers. Lastly, you can get a channel from the FileInputStream, FileOutputStream, ServerSocket,Socket, and RandomAccessFile classes. Unfortunately, adding these new IO metaphors to the existing crowded field (streams, pipes, readers, writers) is extremely confusing to most programmers. Also, the metaphors overlap and their APIs are intertwined. Overall, the complexity and overlapping functionality of the numerous IO classes is its biggest pitfall.
18 Item 2
Buffers. Buffers are generic data containers for random access manipulation of a single data type. These are integrated with the Charsets and Channels classes. Each buffer contains a mark, position, limit, and capacity value (and corresponding methods for manipulation). The position can be set to any point in the buffer. Buffers are set in a mode (reading or writing) and must be "flipped" to change the mode.