Java 2 Platform Compatibility


Java 2 Platform v1.3
Compatibility with Previous Releases

SDK Documentation



For information about incompatibilities between versions 1.2 and 1.1 of the Java platform, see the compatibility documentation for the Java 2 Platform, v1.2.

For information about incompatibilities between versions 1.0 and 1.1 of the Java platform, see the compatibility documentation for the JDK 1.1 software.

See the Clarifications and Amendments document for a summary of changes that have been made to the specification of the Java programming language since the publication of the original Java Language Specification .

Binary Compatibility


As long as the Javac compiler's '-target 1.2' command-line option is not used, downward binary compatibility is generally supported, though not guaranteed. That is, class files built with a Java 2 SDK compiler, but relying only on APIs defined in versions 1.0 or 1.1 of the Java platform, will generally run on 1.0 and 1.1 versions of the Java virtual machine, but this "downwards" compatibility has not been extensively tested and cannot be guaranteed. Of course, if the class files depend on any new Java 2 Platform APIs, those files will not work on earlier platforms.

In general, the policy is that:


  • Maintenance releases (for example 1.2.1, 1.2.2) within a family (1.2.x) will maintain both upward and downward binary-compatibility with each other.


  • Functionality releases (for example 1.2, 1.3) within a family (1.x) will maintain upward but not necessarily downward binary-compatibility with each other.

Some early bytecode obfuscators produced class files that violated the class file format as given in the virtual machine specification. Such improperly formatted class files will not run on the Java 2 SDK's virtual machine, though some of them may have run on earlier versions of the virtual machine. To remedy this problem, regenerate the class files with a newer obfuscator that produces properly formatted class files.

Source Compatibility


Downward source compatibility is not supported. If source files use new language features or Java 2 Platform APIs, they will not be usable with an earlier version of the Java platform.

In general, the policy is that:


  • Maintenance releases do not introduce any new language features or APIs, so they maintain source-compatibility in both directions.


  • Functionality releases and major releases maintain upwards but not downwards source-compatibility.

Deprecated APIs are methods and classes that are supported only for backwards compatibility, and thecompiler will generate a warning message whenever one of these is used, unless the -nowarn command-line option is used. It is recommended that programs be modified to eliminate the use of deprecated methods and classes, though there are no current plans to remove such methods and classes entirely from the system.

Some APIs in the sun.* packages have changed. These APIs are not intended for use by developers. Developers importing from sun.* packages do so at their own risk. For more details, see Why Developers Should Not Write Programs That Call sun.* Packages.

Incompatibilities in the Java 2 Platform, Standard Edition, v1.3


  1. New class java.util.Timer has been added in version 1.3 of the Java 2 Platform, making two classes named Timer:
    • java.util.Timer
    • javax.swing.Timer
    The introduction of java.util.Timer will cause a source-level incompatibility in existing code that has these two import statements:
    import java.util.*;
    import javax.swing.*;
    and refers to javax.swing.Timer by its unqualified name, as in, for example
    Timer t;
    The ambiguous reference to class Timer can be resolved in favor of javax.swing.Timer by adding a third import statement:
    import javax.swing.Timer;
    With this third import statement in place, the source code will compile and have the same behavior as in previous versions of the platform.


  2. The implementation of method java.lang.Double.hashcode has been changed in Java 2 SDK, v1.3 to conform to the API specification. A typographical error in the specification has also been corrected. The specification for method hashcode previously contained the following sentence:
    "That is, the hashcode is the value of the expression:
    where v is defined by:
    long v = Double.doubleToLongBits(this.longValue());"
    The last line in this sentence has been corrected in the 1.3 API specification to read
    long v = Double.doubleToLongBits(this.doubleValue());
    The method's implementation in the SDK has been changed to return
    (int)(bits ^ (bits >>> 32))
    in conformance with the specification, where bits is doubleToLongBits(value). In previous versions of the SDK, method hashcode returned
    (int)(bits ^ (bits >> 32))
    This change in implementation is not expected to affect the behavior of existing applications because hashcode returns a truncated integer value.


  3. New Permission class java.sql.SQLPermission has been added in version 1.3 of the Java 2 Platform. The SecurityManager will check the SQLPermission when code that is running in an applet calls any of the following methods:
    java.sql.DriverManager.setLogStream  (deprecated)

    Under J2SE 1.3, an exception will be thrown when an applet without the appropriate SQLPermission attempts to set the log writer.


  4. The internal implementation of the Java Sound APIs (in class in version 1.3 checks javax.sound.sampled.AudioPermission . The new check means that, under 1.3, applets must be given the appropriate AudioPermission to access audio system resources, whereas this was not the case in previous versions of the platform.


  5. JInternalFrames are no longer visible by default. Beginning with version 1.3 of the Java 2 Platform, developers need to set the visibility of each JInternalFrame to true in order to have it show up on the screen. In previous versions of the platform, the visibility of JInternalFrames was true by default.

    Why the change? The rule for default visibility in Swing is that only top-level components, such as JFrame and JDialog, have default visibility false; the remaining components have default visibility true. This is so that once a JFrame is constructed, one call to setVisible(true) on the JFrame will show it and all of its contents.

    Although JInternalFrame is not really a top-level component, it needs to behave like a JFrame in many ways. In particular, it needs to fire JInternalFrame events corresponding to Window events on JFrames. One such event, INTERNAL_FRAME_OPENED, is fired in response to the initial visibility change from false to true; with no such change prior to version 1.3, the event wasn't being fired.

    In order to fix this bug, and to make JInternalFrame more compatible with its heavyweight cousin JFrame, the default visibility of JInternalFrame has been changed to false beginning with version 1.3 of the Java 2 Platform. Therefore, to show an internal frame, just add the call to setVisible(true) after adding the frame to its parent.

    To ensure that your JInternalFrames are visible on 1.2.x or 1.3, you need to be sure to call setVisible. There is no penalty for making this call on 1.2 even though the frames will be visible by default.


  6. In version 1.3, the TableColumn.getHeaderRenderer method returns null by default. Because of that, it cannot be used to get the default header renderer. Instead, you can use the new JTableHeader.getDefaultRenderer method to get the default header renderer.

    In cases where you need the same code to work on 1.2.x and 1.3, you can do so. In places where you were counting on the getHeaderRenderer method to return the default renderer, you can instead create a new renderer. An example is shown below. This will work on 1.2.x and 1.3.

    /*Original code*/
    DefaultTableCellRenderer hr =
    /*Fixed code*/
    DefaultTableCellRenderer hr  = new DefaultTableCellRenderer();


  7. Because JTable's default text editor is smarter in version 1.3 about data types, it now gives setValueAt objects of the appropriate type, instead of always specifying strings. For example, if setValueAt is invoked for an Integer cell, then the value is specified as an Integer instead of a String. If you implemented a table model, then you might have to change its setValueAt method to take the new data type into account. If you implemented a class used as a data type for cells, make sure that your class has a constructor that takes a single String argument.


  8. In releases 1.2.x it was possible for sufficiently trusted code to modify final fields by first calling Field.setAccessible(true) and then calling Field.set(). This was clearly a bug since the specification for Field.set() stated that an IllegalAccessException would be thrown in this case. This bug has been fixed in 1.3, and program code should not attempt to rely on the improper behavior that was formerly possible because of the bug.


  9. A bug (bugID 4250960) in versions 1.2, 1.2.1 and 1.2.2 of the Java 2 SDK and Java 2 Runtime Environment allowed sufficiently trusted code to change the value of final fields by first calling java.lang.reflect.Field.setAccessible(true) and then calling Field.set(). The ability to modify final fields in this manner is a bug because it is a violation of the specification for Field.set(), which states that an IllegalArgumentException should be thrown when an attempt is made to modify a final field.

    This bug is fixed in version 1.3, and program code should not attempt to rely on the improper behavior that was formerly possible because of the bug.

    Note that non-static final fields can still be set through the JNI Set<type>Field routines .


  10. The specification and behavior of the constructors BasicPermission(String name) and BasicPermission(String name, String actions) in class have been modified in version 1.3 of the Java 2 Platform. When the name parameter is null, the constructors now throw a NullPointerException. When name is an empty string, the constructors now throw an IllegalArgumentException. This change of behavior is inherited by subclasses of BasicPermission.

    The change also affects the behavior of java.lang.System.getProperty() and java.lang.System.setProperty() whose implementations construct an instance of PropertyPermission, a subclass of BasicPermission. Under the change, a call to getProperty or setProperty with an empty property name (that is, getProperty("") or setProperty("", value)) will result in an IllegalArgumentException. In previous versions of the platform, such a call would return quietly with no exception.


  11. The behavior of has changed slightly for cases in which a URL instance is constructed from a String. In previous versions of the Java platform, a final slash ( '/') would be added to a URL when the URL was constructed without one. For example, consider this code:
    URL url = new URL("");
    In previous releases, this code would produce the following output.
    In 1.3, the trailing slash is not automatically appended, so that the output of the above code is now
    The previous behavior was technically a bug, and it is not expected that this change will cause any compatibility problems with previous releases.


    • The introduction of a new implementation of the javac compiler in version 1.3 has the following compatibility ramifications.

      • Inherited Members of an Enclosing Class are Now Accessible
        The Java Language Specificaton, Second Edition, states that inherited members of a class are accesible within that class, including any nested classes. In 1.1 and 1.2 versions of the Java 2 SDK, the compiler considered a member accessible within a nested class only if it was actually declared in an enclosing class. The new compiler in the Java 2 SDK, v1.3 has been brought into conformance with the specification.


      • Hiding of Local Variables and Parameters
        The Java Language Specification requires that an error be reported when a local variable or catch clause parameter is declared within the scope of a like-named method parameter, local variable, or catch clause parameter. However, the old compiler enforced it somewhat erratically. The specification has been clarified so that the rule applies only to variables and parameters belonging to a single method. Where a method is nested within another method, e.g., as a member of a local class, local variables and parameters of the inner method may freely shadow those of the outer method.


      • Name Conflicts Between Types and Subpackages
        According to section 7.1 of the Java Language Specification, Second Edition, it is illegal for a package to contain a class or interface type and a subpackage with the same name. This rule was almost never enforced prior to version 1.3. The new compiler now enforces this rule consistently. A package, class, or interface is presumed to exist if there is a corresponding directory, source file, or class file accessible on the classpath or the sourcepath, regardless of its content.


      • Qualified Names in Constant Expressions
        According to section 15.28 of the Java Language Specification, Second Edition, a qualified name that is a constant expression must be of the form TypeName.identifier. Thus, regardless of whether the field foo itself is a constant, an expression, where x is a variable or any other expression, may not be used in a context where a constant expression is required. Prior to version 1.3, javac silently accepted such constructions, treating x as if had been replaced by its type, and ignoring any side effects that the expression might peform.


      • Member Classes of Interfaces are Now Inherited by Implementing Classes
        Prior to version 1.3, member classes of interfaces were not inherited by implementing classes. This was an oversight in the implementation. The specification requires that the member classes be inherited, in keeping with the principle that they should be treated analogously to fields.


    • In version 1.3, has been optimized to buffer incoming data for improved performance. As a side effect of this change, ObjectInputStream calls the multi-byte read(byte[], int, int) method of the underlying stream more often than it did previously. Consequently, underlying stream classes that implement this method incorrectly are more likely to trigger serialization failures. To avoid the possibility of unexpected behavior, it is critical that the underlying stream implement both the single-byte read() and multi-byte read(byte[], int, int) methods properly.


    • Version 1.2 of the Java 2 Runtime Environment included a client side adapter for the Internet-Intranet Input Method Protocol (IIIMP), a Sun Microsystems technology which enables the use of server-based input methods over the network. This adapter was included to allow the evaluation of this protocol at a time when there was no public interface that would let users install the adapter into a Java runtime environment as a separate software component. Version 1.3 of the Java 2 platform provides a public input method engine SPI, so that the adapter, like other input systems, can now be developed and distributed as a separate product and installed into any implementation of the Java 2 platform. A version of the IIIMP adapter that uses the SPI is currently being developed by Sun Microsystems. To obtain current information, go to the Solaris Developer Connection and search for "IIIM".

      Environments set up to allow text entry using a server-based input method should use instead another solution such as host input methods or the IIIMP client-side adapter from Sun.


    • The previous versions of JVMs and native libraries in the JDK were compiled in C++ " -compat=4" mode so as to be compatible with native C++ code that was written in the ARM-based pre-ANSI/ISO C++ (such as used with Sun Workshop SC4.2 and earlier C++ compilers). Starting from J2SE 1.3.0 onwards, the JVM and native libraries are compiled using the "standard" mode corresponding to ANSI/ISO C++. This change means that existing native C++ source code that uses the old pre-ANSI/ISO C++, and which used to work with the old versions of the JVMs, will be incompatible with J2SE 1.3.0, especially if you use C++ exceptions. Such native C++ code should be ported to "standard" ANSI C++ mode to work with J2SE 1.3.0 and later.

      Version 1.3.0 of the Java virtual machine for Solaris Operating Environment was built under Solaris 2.6 using Sun Workshop 5.0 C++ compiler in "standard" (ANSI/ISO C++) mode using ""classic" iostreams.


    • Prior to J2SE 1.3.0, the javac compiler for Microsoft Windows platforms treated directory names in package paths in a case-insensitve manner. Beginning with J2SE 1.3.0, the javac compiler treats directory names in a case-sensitive manner. The javac compiler in J2SE 1.3.0 will emit a "cannot resolve symbol" error if directory names in a package path are not letter-for-letter case matched to package names.