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. The following tips help to avoid
portability problems. Portability rules like those listed here were
the focus of Sun's now-defunct
"100% Pure Java" certification
program and branding campaign.
- Native methods
-
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 platform, 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. The method was
deprecated but has been reintroduced in Java
5.0.
- Undocumented classes
-
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 part of the Java platform specification. Nothing prevents 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.
- Implementation-specific features
-
Portable code must not rely on features
specific to a single implementation. For example, 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. Any program that depends on such extensions is
obviously not portable to other platforms.
Microsoft's
proprietary extension of the Java platform resulted in legal action
between Sun and Microsoft and ultimately caused Microsoft to
discontinue ongoing support for Java.
- Implementation-specific bugs
-
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, and ultimately may be fixed.
- Implementation-specific behavior
-
Sometimes
different platforms and different implementations 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 indicate
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.
- Standard extensions
-
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 extensions installed.
- Complete programs
-
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.
- Hardcoded filenames
-
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 constant.
- Line separators
-
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 PrintStream or
PrintWriter, which automatically terminates a line
with the line separator appropriate for the platform, or use the
value of the line.separator system property. In
Java 5.0 and later, you can also use the
"%n" format string to
printf( ) and format() methods
of java.util.Formatter and related classes.
|