7.2. Portability Conventions and Pure Java Rules
Sun's motto, or core value proposition, for Java is "Write once,
run anywhere." Java makes it easy to write portable
programs, but Java programs do not automatically run successfully
on any Java platform. To ensure portability, you must follow a
few fairly simple rules that can be
summarized as follows:
Portable Java code can use any methods in the core Java
APIs, including methods implemented as
native methods. However, portable code
must not define its own native methods. By their very
nature, native methods must be ported to each new
so they directly subvert the "Write once, run anywhere"
promise of Java.
The Runtime.exec( ) method
Calling the Runtime.exec() method
to spawn a process and execute an external command on the
native system is rarely allowed in portable code. This is
because the native OS command to be executed is never guaranteed
to exist or behave the same way on all platforms. The
only time it is legal to use
Runtime.exec() is when the user is
allowed to specify the command to run, either by typing the
command at runtime or by specifying the command in a
configuration file or preferences dialog box.
The System.getenv( ) method
Using System.getenv() is nonportable,
without exception. The method has actually been
deprecated for this reason.
Portable Java code must use only classes and interfaces that
are a documented part of the Java platform. Most Java
implementations ship with additional undocumented public
classes that are part of the implementation, but not
of the Java platform specification. There is nothing to
prevent a program from using and relying on these
undocumented classes, but doing so is not portable because
the classes are not guaranteed to exist in all Java
implementations or on all platforms.
The java.awt.peer package
The interfaces in the java.awt.peer package
are part of the Java platform, but are documented for use by
AWT implementors only. Applications that use these
interfaces directly are not portable.
Portable code must not rely on features specific to a single
implementation. For example, in a widely controversial
move, Microsoft distributed a version of the Java runtime system
that included a number of additional methods that were not part of
the Java platform as defined by Sun. Legal action between
Sun and Microsoft is pending because of this. Any program
that depends on the Microsoft-specific extensions is
obviously not portable to other platforms.
Just as portable code must not depend on
implementation-specific features, it must not depend on
implementation-specific bugs. If a class or method behaves
differently than the specification says it should, a
portable program cannot rely on this behavior, which may be
different on different platforms.
Sometimes different platforms and different implementations
may present different behaviors, all of which are legal
according to the Java specification. Portable code must not
depend on any one specific behavior. For example,
the Java specification does not specify whether
threads of equal priority share the CPU or if one
long-running thread can starve another thread at the same
priority. If an application assumes one behavior or the
other, it may not run properly on all platforms.
Portable code can rely on standard extensions to the Java
platform, but, if it does so, it should clearly specify which
extensions it uses and exit cleanly with an appropriate
error message when run on a system that does not have the
Any portable Java program must be complete and
self-contained: it must supply all the classes it uses,
except core platform and standard extension classes.
Defining system classes
Portable Java code never defines classes in any of the
system or standard extension packages. Doing so violates
the protection boundaries of those packages and exposes
package-visible implementation details.
A portable program contains no hardcoded file or directory
names. This is because different platforms have
significantly different filesystem organizations and use
different directory separator characters. If you need to
work with a file or directory, have the user specify the
filename, or at least the base directory beneath which the file
can be found. This specification can be done at runtime, in
a configuration file, or as a command-line argument to the
program. When concatenating a file or directory name to
a directory name, use the File()
constructor or the File.separator
Different systems use different characters or sequences of
characters as line separators. Do not hardcode "\n", "\r",
or "\r\n" as the line separator in your program. Instead,
use the println() method of
PrintWriter, which automatically
terminates a line with the line separator appropriate for
the platform, or use the value of the
line.separator system property.
Mixed event models
The AWT event model changed dramatically between Java 1.0
and Java 1.1. Although it is often possible to mix these
two event models in a program, doing so is not technically
The previous rules are the focus of Sun's "100% Pure
Java" portability certification program; you can find out more
about this program and read more about the "Pure Java"
Copyright © 2001 O'Reilly & Associates. All rights reserved.