Java 2 Platform Compatibility with Previous Releases

   

Java 2 Platform, Standard Edition Version 1.4.0
Compatibility with Previous Releases

SDK Documentation

 

 

Contents

This document contains information on the following topics:

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

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

The Java 2 SDK, v1.4 is upwards binary-compatible with Java 2 SDK, v1.3 except for the incompatibilities listed below. This means that, except for the noted incompatibilities, class files built with version 1.3 compilers will run correctly in the Java 2 SDK, v1.4.

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.3, 1.4) 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

The Java 2 SDK versions 1.2, 1.3, and 1.4 are upwards source-compatible with JDK software versions 1.0 and 1.1, except for the incompatibilities listed below. This means that, except for the noted incompatibilities, source files written to use the language features and APIs defined for 1.0 and 1.1 can be compiled and run in the Java 2 SDK (all versions). 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 Between Java 2 Platform, Standard Edition, v1.4.0 and v1.3

J2SE 1.4.0 is strongly compatible with previous versions of the Java 2 Platform. Almost all existing programs should run on J2SE 1.4.0 without modification. However, there are some minor potential incompatibilities with 1.3 that involve rare circumstances and "corner cases" that we are documenting here for completeness.

 

  1. Beginning with version 1.4 of the Java 2 Platform, class javax.swing.tree.DefaultTreeModel allows a null root node. In previous versions, DefaultTreeModel would not allow a null root, even though the specification for TreeModel indicated a null root was valid. DefaultTreeModel now allows setting a null root, as well as a null root in the constructor. As part of this change, the specification for DefaultTreeModel.setRoot() has been revised.

    The old specification for DefaultTreeModel.setRoot() was:

    Sets the root to root. This will throw an IllegalArgumentException if root is null.

    The new DefaultTreeModel.setRoot() specification says:

    Sets the root to root. A null root implies the tree is to display nothing, and is legal.

     

  2. If a serializable nested class contains explicit references to a class object (for example, "Foo.class"), then the computed value of the default serial version UID for both the nested class and its enclosing class will be different in J2SE 1.3 and J2SE 1.4. The difference is due to the fact that the computation of the serial version UID is sensitive to modifications made in the javac compiler between J2SE 1.3 and J2SE 1.4.

    To avoid this problem affecting your applications, we recommend that you add an explicit serial version UID to your serializable classes. You can use the serialver tool to obtain the serial version UID of classes compiled with the J2SE 1.3 javac compiler.

     

  3. Beginning with J2SE 1.4.0, public static field DefaultPainter in class javax.swing.text.DefaultHighlighter is final. In previous versions of the Java 2 Platform, Standard Edition, this field was non-final.

     

  4. The way in which HTML forms are modeled internally in the implementation of the Java 2 Platform has changed in J2SE 1.4.0. Previously, any attributes of a form would be stored in the attributeset of all of the children character elements. In J2SE 1.4.0, an element is created to represent the form, better matching that of the html file itself. This allows for better modeling of the form, as well as consistant writing of the form. This change was made to address bug 4200439.

    This change will effect developers who relied on forms being handled loosely. As an example, pre-1.4.0 implementations would previously treat the following invalid html

      <table>
        <form>
      </table>
      </form>
    

    as

     

      <form>
        <table>
        </table>
      </form>
    

    J2SE 1.4.0 instead treats it as:

      <table>
        <form>
        </form>
      </table>
    

    While this change likely will not impact many developers, there is the possibility you will need to update your code. If you had previously been expecting the attributes of the leaf Elements to contain the Form's attributes, you will now have to get the attributes from the Form Element's AttributeSet.

     

  5. The value of static final field MOUSE_LAST in class java.awt.event.MouseEvent has changed to 507 beginning in J2SE 1.4.0. In previous versions of the Java 2 Platform, the value of MOUSE_LAST was 506.

    Because compilers hard-code static final values at compile-time, code that refers to MOUSE_LAST and that was compiled against a pre-1.4.0 version of java.awt.event.MouseEvent will retain the old value. Such code should be recompiled with the version 1.4.0 compiler in order to work with J2SE 1.4.0.

     

  6. Changes have been made to make the APIs for the CORBA technology shipped in J2SE 1.4.0 compliant to the CORBA 2.3 mapping as specified by the OMG documents referenced in CORBA Compatibility Information . Follow the link for information regarding all of the API changes related to CORBA functionality between J2SE v1.3 and v1.4.0, as well as a listing of all OMG specifications with which J2SE 1.4.0 complies.

     

  7. Beginning with J2SE 1.4.0, ObjectOutputStream's public one-argument constructor requires the "enableSubclassImplementation" SerializablePermission when invoked (either directly or indirectly) by a subclass which overrides ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared .

    Also beginning with J2SE 1.4.0, ObjectInputStream's public one-argument constructor requires the "enableSubclassImplementation" SerializablePermission when invoked (either directly or indirectly) by a subclass which overrides ObjectInputStream.readFields or ObjectInputStream.readUnshared .

    This change will not affect the great majority of applications. However, it will affect any ObjectInputStream/ObjectOutputStream subclasses which override the putFields or readFields methods without also overriding the rest of the serialization infrastructure.

     

  8. The Javac bytecode compiler in J2SE 1.4.0 is more strict than in previous versions in enforcing compliance with the Java Language Specification. The new compiler may not compile existing code that does not strictly conform to the Java Language Specification, even though that code may have compiled with earlier versions of the compiler.

    The following are some examples of situations in which the J2SE 1.4.0 compiler is stricter.

    • The compiler now detects unreachable empty statements as required by the language specification. Here are two examples of fairly common cases that the compiler now detects and rejects.:

      return 0;/* exit success */;
      
      and
      {
          return f();
      } catch (Whatever e) {
          throw new Whatever2();
      };
      

      Note the extra semicolon in both cases, which the compiler now correctly regards as unreachable empty statements. In addition, some automatically generated source code may generate unreachable empty statements.

       

    • The compiler now rejects import statements that import a type from the unnamed namespace. Previous versions of the compiler would accept such import declarations, even though they were arguably not allowed by the language (because the type name appearing in the import clause is not in scope). The specification is being clarified to state clearly that you cannot have a simple name in an import statement, nor can you import from the unnamed namespace.

      To summarize, the syntax

      import SimpleName;
      
      is no longer legal. Nor is the syntax
      import ClassInUnnamedNamespace.Nested;
      

      which would import a nested class from the unnamed namespace. To fix such problems in your code, move all of the classes from the unnamed namespace into a named namespace.

  9. As of J2SE 1.4.0, the javac bytecode compiler uses "-target 1.2" by default as opposed to the previous "-target 1.1" behavior. See the reference page for the javac compiler for descriptions of these behaviors. One of the changes involved in targeting 1.2 is that the compiler no longer generates and inserts method declarations into class files when the class inherits unimplemented methods from interfaces. These inserted methods, like all other non-private methods, are included in the default serialVersionUID computation. As a result, if you define an abstract serializable class which directly implements an interface but does not implement one or more of its methods, then its default serialVersionUID value will vary depending on whether it is compiled with the J2SE 1.4 version of javac or a previous javac.

    For background information on these methods inserted by earlier versions of javac, see bug

    4043008.

  10. Source incompatibility - The JDBC 3.0 API, included as part of the J2SE 1.4 platform, introduces two new interfaces and adds several new methods to existing interfaces. Drivers and applications that use earlier versions of the JDBC API are binary compatible with the J2SE 1.4 platform and will run with no problem. However, the changes made in the JDBC 3.0 API are not source compatible. Drivers and applications that implement the JDBC interfaces must be updated to reflect the changes in order to build successfully. Chapter 6 of The JDBC 3.0 Specification gives a complete list of what must be done to be compliant with the JDBC 3.0 API, and thereby be source compatible with the J2SE 1.4 platform.

  11. Prior to J2SE 1.4, a FileNotFoundException would be thrown if the file type was known and the response code was greater than or equal to 400. Otherwise no exception would be thrown.

    The correct behavior as implemented in J2SE 1.4 is for URLConnection.getInputStream to throw an IOException for all http errors regardless of the file type and throw FileNotFoundException, which is a subclass of IOException, only if the http response indicates that the resource was not found. In other words, the FileNotFoundException is thrown only if the response code is 404 or 410.

    As part of this change, HttpURLConnection.getErrorStream now can be used to read the error page returned from the server. Prior to J2SE 1.4, getErrorStream always returned null. Also, method HttpURLConnection.getResponseCode works correctly in J2SE 1.4.

  12. The assert keyword has been added to the Java Programming Language in J2SE 1.4. Because of the new keyword, existing programs that use "assert" as an identifier will not be in conformance with J2SE 1.4. The addition of this keyword does not, however, cause any problems with the use of preexisting binaries ( .class files). In order to ease the transition from pre-J2SE 1.4 releases in which assert is a legal identifier to J2SE 1.4 where it isn't, the Javac bytecode compiler supports two modes of operation in J2SE 1.4.

    • In the normal mode of operation, the compiler accepts programs conforming to the specification for the previous release (J2SE 1.3). Assertions are not permitted, and the compiler generates a warning if the assert keyword is used as an identifier.

       

    • In an alternate mode of operation, the compiler accepts programs conforming to the specification for J2SE 1.4. Assertions are permitted, and the compiler generates an error message if the assert keyword is used as an identifier.

    To enable assertions, use the following command line switch.

    -source 1.4
    

    In the absence of this flag, the behavior defaults to "1.3" for maximal source compatibility. Support for 1.3 source compatibility is likely to be phased out over time.

  13. The API specification for interface AppletContext has been modified to enable applet developers to stream data and objects for persistent use during a browser session. This eliminates the need for developers to use static classes to cache data and objects, but it introduces a potential binary incompatibility. Any existing applications containing classes that implement the AppletContext interface will not be compatible with the new AppletContext specification. Such classes will have to be modified to implement the revised AppletContext API. In practice, the only applications that commonly implement AppletContext are those that act as applet containers, such as Java Plug-in and appletviewer. The impact of this potential incompatibility is therefore expected to be minimal.

  14. J2SE 1.4 introduces significant changes in the Socket API, one of which is the addition of a new abstract method to the SocketImpl abstract class. Because of the new method, if a subclass of SocketImpl was created prior to J2SE 1.4, then compilation against the 1.4 javac will fail because there is no implementation provided for the new method.

    Note that binary compatibility is enforced, and existing class files for such a subclass will still work as expected.

    Few applications subclass SocketImpl, and the impact of this potential incompatibility is expected to be minimal. Developers who do subclass SocketImpl have two ways to deal with this change:

    • Use a class file compiled on J2SE 1.3.x (or earlier).

    • Provide an implementation for the new methods. An simple example that assumes a straight TCP/IP implementation and ignores the timeout value is provided below. Of course, we recommend use of a proper implementation that respects the timeout value. A simple implementation for sendUrgentData() that throws an exception is all that is needed provided that supportsUrgentData() hasn't been overwritten to return "true".

                                             
      
          /**
           * Creates a socket and connects it to the specified address on
           * the specified port.
           * @param address the address
           * @param timeout the timeout value in milliseconds, or zero for no timeout.
           * @throws IOException if connection fails
           * @throws  IllegalArgumentException if address is null or is a
           *          SocketAddress subclass not supported by this socket
           * @since 1.4
           */
          protected void connect(SocketAddress address, int timeout) 
              throws IOException {
                 if (address == null || !(address instanceof InetSocketAddress))
                    throw new IllegalArgumentException("unsupported address type");
                 InetSocketAddress addr = (InetSocketAddress) address;
                 if (addr.isUnresolved())
                    throw new UnknownHostException(addr.getHostName());
                 this.port = addr.getPort();
                 this.address = addr.getAddress();
      
                 try {
                     connect(this.address, port);
                   return;
                 } catch (IOException e) {
                  // everything failed
                    close();
                    throw e;
                 }
          }
      
          /**
           * Send one byte of urgent data on the socket.
           * The byte to be sent is the low eight bits of the parameter
           * @param data The byte of data to send
           * @exception IOException if there is an error
           *  sending the data.
           * @since 1.4
           */
          protected void sendUrgentData (int data) throws IOException {
              throw new IOException("Unsupported operation");
          }
                                          

  15. The J2SE 1.4 platform includes the Java Secure Socket Extension (JSSE) API. In J2SE 1.4, the JSSE implementation recognizes system property com.sun.net.ssl.dhKeyExchangeFix, and this variable has a default value of " true" in J2SE 1.4. In the previously released JSSE 1.0.2 optional package, the default value of the property was " false". Cypher suites that use the DH key exchange will be affected by this change in property value. Such suites are used comparitively rarely, so this potential incompatibility is not expected to have a large impact.

    Background: The orignally released optional package version of the JSSE API contained a bug that caused incorrect encoding of DSA signatures when those signatures were used as part of the server key exchange message. This bug meant that JSSE was not in conformance to the key exchange specification, and it was the source of incompatibilities between JSSE and SSL implemenations from other vendors. In an attempt to fix this situation, optional package JSSE 1.0.2 introduced system property com.sun.net.ssl.dhKeyExchangeFix. Setting this property to " true" meant that JSSE 1.0.2 would operate with the bug fixed and thus be compatible with other SSL implementations. When the property value was " false", JSSE 1.0.2 would operate with the bug not fixed so as to be compatible with previous JSSE releases. In JSSE 1.0.2, the default value of the property was " false"; in J2SE 1.4, the default value is " true", ensuring compatibility between J2SE 1.4 and other SSL/TLS implementations.

  16. Beginning with version 1.4 of the J2SE platform, policy files used by the default policy implementation must be encoded in the UTF-8 character encoding. Existing policy files with non-ASCII characters (which would have been encoded in some platform character encoding) must be converted to UTF-8. The Java 2 SDK, Standard Edition's native2ascii tool can be used to assist with this conversion.

  17. A change in behavior was introduced in J2SE 1.4.0 as a fix for 4395290. The changed behavior is also part of J2SE 1.4.1. In the new behavior, dragExit() is called on the DropTarget and on the DropTargetListener registered with it only when the mouse pointer has exited the operable part of the drop site for this DropTarget during a drag operation. Prior to J2SE 1.4.0, these methods were also called immediatelly before drop() is called on the DropTarget or the DropTargetListener respectively.

    The old behavior was documented in the Drag and Drop Specification for J2SE 1.3, but was inconsistent with the Java 2 Platform API Specification. The old behavior was also inconvenient and imposed a significant impact on the usability of Drag and Drop in Swing.

    Starting with J2SE 1.4.0, the behavior matches the Java 2 platform API Specification and the Drag and Drop Specification was updated to reflect this change.

  18. A change in behavior was introduced in J2SE 1.4.0 as a fix for 4426794 and 4435403. The changed behavior is also part of J2SE 1.4.1. Prior to J2SE 1.4.0, drag notifications were always dispatched to the top-most Component under the mouse cursor. If this Component does not have an associated drop target, these notifications are discarded. This design has two major flaws:

    • We have to ignore a Swing glass pane during drag notification targeting, because it would consume all drag notifications otherwise. This prevents developers from using a Swing glass pane as a drop target.

    • To implement drop support on a compound Component, such as a JColorChooser, such that the Component would accept a drop anywhere inside of it, developers are forced to install drop targets on all descendants of the compound Component. This is unwieldy and inefficient.

    In the new behavior, drag notifications are dispatched to the top-most Component under the mouse cursor with an active drop target.

  19. As a result of the new focus architecture introduced in 1.4.0, the following incompatibilities were introduced:
    • Focus traversal keys (in most cases this means the TAB key) are now consumed, which can cause problems if a program depends on a key listener being notified of these key events. Previously, AWT components saw these events and had an opportunity to consume them before AWT initiated focus traversal. To avoid focus traversal keys being consumed, use the following code:
          component.setFocusTraversalKeysEnabled(false);
      
      where component is the Component that is firing the key events. Focus traversal can then be handled manually. Alternatively, the code can use an AWTEventListener or KeyEventDispatcher to pre-listen to all key events. For more information, see bug 4650902.

       

    • The default focus traversability for all components is now true. Previously, some components (in particular, all lightweights), had a default focus traversability of false. Note that despite this change, however, the DefaultFocusTraversalPolicy for all AWT containers will preserve the traversal order of previous releases.

       

    • A request to focus a non-focus traversable (ie. non-focusable) component will be denied. Previously, such requests were granted.

       

    • Window.toFront() and Window.toBack now perform no operation if the window is not visible. Previously, the behavior was platform-dependent.

      Changes specific to Microsoft Windows:

       

    • Window.toBack() changes the focused window to the top-most window after the Z-order change.
    • requestFocus now allows cross-window focus change requested in all cases. Previously, requests were granted for heavyweights, but denied for lightweights.

     

  20. As of release 1.4.0, when the last window is disposed of and no more events are in the event queue, the event-dispatching thread may exit, which causes the program to exit. See bug #4030718 for more information, including a workaround.