Team LiB
Previous Section Next Section

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.

    Team LiB
    Previous Section Next Section