Solaris. But we wanted to show that the new libraries were cross-platform, so we wanted to
run a client on Windows and the server on Unix.
We had copied our complete source tree over to a Windows box and were about to issue the
make command when we stopped. Java was supposed to be portable. So, just for yucks, we
simply copied the object files to the Windows box and fired up the demo. It just worked.
After we got our jaws off the floor, we finally understood what this virtualization thing was
The overall Java environment has taken a lot of grief over the “write once, run anywhere”
slogan. Sometimes this grief is justified. The graphics may not be exactly the same on all sys-
may not run optimally, leading to the notion of “write once, tune everywhere.” Those doing
numerically intensive scientific programming certainly object to the inability of Java to take
advantage of specialized floating-point features in various platforms (and are more than will-
ing to give up getting the same answer on all platforms if that is the price of the added effi-
ciency). And there are times when it isn't even clear what it means to “run everywhere.” I re-
member long discussions in the earlier days of Java on whether “running everywhere” meant
that your program would look the same everywhere, or meant that your program would adopt
the “look and feel” of the platform on which it was running without changing the code. Each
of these was a plausible interpretation (at least, each was supported by some member of the
Java community), but they were mutually incompatible.
Although many of these criticisms may be true, the fact is that the JVM gives the programmer
a better virtualization platform than any other. Writing portable Java code is not only possible,
it is the default. Writing portable code in any other system language is very difficult. And
for system programming (which often confines its graphical user interface to println() and
read() ), the problems with portability are rarely encountered.
But saying that such problems are rarely encountered doesn't mean that they are never en-
countered (otherwise, I would have said “never”). Avoiding these problems generally requires
that you be aware of operating system or other platform idiosyncrasies, and then find the prop-
er abstraction within the Java system that will let you avoid these idiosyncrasies.
As an example of this, let's revisit some of the code that we wrote in Chapter 5 that allowed
us to read and write the player data to the filesystem. As you may recall, we wrote the
player information into a file that was named using the player's unique identifier. But that