Sun Java Solaris Communities My SDN Account Join SDN
 
Archive - Java Technology Products Download

Compatibility with Previous Releases

 

Java 2 SDK
Compatibility with Previous Releases

SDK Documentation

Japanese

Contents

This document contains information on the following topics:

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

Version 1.2 of the Java 2 SDK is upwards binary-compatible with JDK software versions 1.0 and 1.1 except for the incompatibilities listed below. This means that, except for the noted incompatibilities, class files built with version 1.0 or 1.1 compilers will run correctly in 1.2.

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 1.2 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 1.2 APIs, those files will not work on earlier platforms.

In general, the policy is that

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

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

Some early Java bytecode obfuscators produced class files that violated the class file format as given in the Java virtual machine specification. Such improperly formatted class files will not run on the 1.2 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

Version 1.2 of the Java 2 SDK is 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 version 1.2.

Downward source compatibility is not supported. If source files use new language features or 1.2 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 the compiler 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.

Incompatibilities in Version 1.2

The following is intended to be a complete list of all cases in which a program that works under in versions 1.0 or 1.1 of the Java platform would fail to work under version 1.2. Most of these incompatibilites involve rare circumstances and "corner cases" and are not expected to impact most existing programs. If you know of other incompatibilities, please notify us (at address at the bottom of the page). "JLS" refers to the book, The Java Language Specification.

Language Incompatibilities in Version 1.2

Compilers in JDK software versions 1.0 and 1.1 would compile some types of illegal code without producing warnings or error messages. Bug fixes in version 1.2 have made the compiler more stringent in ensuring that code conforms to the Java Language Specification. Many of the incompatibilities described in this section are caused by enforcement of the specification, not by changes in the specification.
  1. Some initializations of int types to long types that were passed by previous compilers will be flagged as errors in version 1.2. In the following program,
    	public class foo {
              int i = 3000000000;
              int j = 6000000000;
    	}
    
    both the initialization to i and j are in error. Prior to version 1.2, only the incorrect initialization of i would have been reported. The initialization of j would have overflowed silently. (Bug 4035346)

  2. Prior to version 1.2, implicit assignment conversion from char to byte and short would be allowed in the case of character literals that fit into 8 bits. Such implicit assignment conversion is not allowed by the compiler in version 1.2. For example,
         byte b = 'b';
      
    will not pass the compiler (Bug 4030496). An explicit cast is required for such conversions.
         byte b = (byte)'b';
      

  3. 0xL is not a legal hex literal and will not be passed by the 1.2 compiler. It was parsed as zero in previous versions of the JDK software. (Bug 4049982)

  4. ''' (and therefore '\u0027') is not a legal char literal and will not be passed by the 1.2 compiler. Use '\'' instead. (Bug 1265387)

  5. \u000D is not legal in string and char literals and will not be passed by the 1.2 compiler. Use \r instead. (Bug 4063147)

    \u000A and \u000D are the CR and LF characters, which terminate lines, even in comments (bug 4086919). Code such as:

           // This comment about \u000D is not legal; it is really two lines.
    

  6. The type void[] is not legal and will not be passed by the 1.2 compiler. (Bug 4034979)

  7. It is not legal to combine the abstract method modifier with private, final, native, or synchronized modifiers. (Bug 1266571)

  8. Double-assignment of final variables, though illegal, would pass previous compilers in some circumstances. For example, the following two samples would pass 1.1.x compilers, even though both involve double-assignment of a final variable:
    public class Example1 {
       public static void main(String[] argv) {
          int k=0;
          for (final int a;;) {
             k++;
             a=k;
             System.out.println("a="+a);
             if (k>3)
                return;
          }
       }
    }
    
    public class Example2
    {
       final int k;
    
       Example2() {
          k = 1;
       }
    
       Example2(Object whatever) {
          this();
          k = 2;
       }
    
       static public void main(String[] args) {
          Example2 t = new Example2(null);
          System.out.println("k is "+ t.k);
       }
    }
    

    Such assignments will not pass the 1.2 compiler. (Bugs 4066275 and 4056774)

  9. It is not legal to reference a non-static field with an apparently static field expression of the form 'Classname.fieldname'. Prior to 1.2, javac silently tolerated such expressions as if they had been written 'this.fieldname'. (Bug 4087127)

  10. Section 5.5 of the JLS specifies that a cast between two interface types is a compile-time error if the interfaces contain methods with the same signature but different return types. The compiler did not generate this compile-time error prior to version 1.2. (Bug 4028359) For example, the following program now generates a compile-time error:
            interface Noisy {
    	    int method();
    	}
    	
    	interface Quiet {
    	    void method();
    	}
    	
    	public class InterfaceCast {
    	    public static void main(String[] args) {
    		Noisy one = null;
    		Quiet two = (Quiet) one;
    	    }
    	}
    

  11. In version 1.2, an assignment expression is not accepted as the third subexpression of a conditional statement. This change has been made because the previous method of parsing conditional expressions did not conform to the Java Language Specification (bug 4092958). For example, the statement
    myVal = condition ? x = 7 : x = 3;
    
    will cause a parse error in 1.2. If this problem occurs in existing code, placing the offending assignment expression in parentheses will cause the code to compile as it did in previous versions of the Java Development Kit:
    myVal = condition ? x = 7 : (x = 3);
    
  12. In previous releases of javac, if a field was initialized to its default value the compiler incorrectly omitted the initialization (bug 1227855). This can lead to different semantics for programs like the following:
    abstract class Parent {
        Parent() {
    	setI(100);
        }
    	
        abstract public void setI(int value);
    }
    	
    public
    class InitTest extends Parent {
        public int i = 0;
    	
        public void setI(int value) {
    	i = value;
        }
    	
        public static void main(String[] args) {
            InitTest test = new InitTest();
    	System.out.println(test.i);
        }
    }
    

    Running this program when compiled with earlier versions of javac produces the incorrect output:
    100
    
    Running this program when compiled with the 1.2 javac produces the output:
    0
    
    Single class examples can be formulated as well:
    public
    class InitTest2 {
        public int j = method();
        public int i = 0;
    	
        public int method() {
    	i = 100;
    	return 200;
        }
    	
        public static void main(String[] args) {
    	InitTest test = new InitTest();
    	System.out.println(test.i);
        }
    }
    

    Before the output was 100. Now it is 0. Note that the same phenomenon can occur in program using reference types and null.

  13. Concerning accessibility in qualified names, JLS 6.6.1 states the following:
    A member (field or method) of a reference (class, interface, or array) type or a constructor of a class type is accessible only if *the type is accessible* [emphasis mine] and the member or constructor is declared to permit access.
    Pre-1.2 compilers did not enforce this rule correctly, granting access if the member or constructor was declared to permit access without regard to the accessibility of the type to which it belongs. Thus the following illegal program would be accepted:
    --------------------
    File CMain.java
    --------------------
    
    import pack1.P1;
    
    public class CMain {
        public static void main(String[] args) {
    	P1 p1 = new P1();
    	// The accesses to field 'i' below are
    	// illegal, as the type of 'p2', the
    	// class type 'pack1.P2', is not accessible.
    	p1.p2.i = 3;
    	System.out.println(p1.p2.i);
        }
    }
    
    --------------------
    File pack1/P1.java
    --------------------
    
    package pack1;
    
    public class P1 {
        public P2 p2 = new P2();
    }
    
    // Note the absence of an access modifier, making
    // 'P2' accessible only from within package 'pack1'.
    
    class P2 {
        public int i = 0;
    }
    

    With the introduction of inner classes in version 1.1 of the Java platform, a member of a class or interface may be another class or interface, as well as a field or method. The change to the enforcement of the 6.6.1 accessibility rules described here has been extended to inner classes as well.

  14. In Java 2 SDK, the compiler detects situations in which a sublcass declares a method with the same name as an abstract, package-private method defined in a superclass from a different package. The compiler produces an error message in such cases. As an example, compiling the files below...
    -----------------
    one/Parent.java
    -----------------
    package one;
     
    public abstract class Parent {
        abstract void method();
    }
    -----------------
    two/Child.java
    -----------------
    package two;
     
    public class Child extends one.Parent {
        void method() {}
    }
    -----------------
    

    ...yields the error message:
    two/Child.java:3: class two.Child is not able to provide an implementation
    for the method void method() declared in class one.Parent because it is
    private to another package.  class two.Child must be declared abstract. 
    public class Child extends one.Parent {
    
    Compilers prior to the Java 2 SDK failed to detect such situations.

  15. Beginning with version 1.2, the compiler properly detects duplicate, nested labels. These are disallowed by the JLS. This is a fix for bug 1241001. This fix makes the following example statement illegal:
    sameName:
    while (condition) {
    	sameName:
    	while (condition2) {
    		break sameName;
    	}
    }
    

  16. Beginning with version 1.2, the compiler properly detects a labeled declaration. These are disallowed by the JLS. This is a fix for bug 4039843.

  17. In the Java 2 SDK, the compiler recognizes a new keyword, strictfp. Therefore, programs can no longer use strictfp as an identifier.

    The 1.2 compiler uses the new keyword to set a modifier bit in the method data structures. The pre-1.2 Java platform specification required that this bit be zeroed. Code written using the new keyword is executed in strict floating-point mode, which is identical to that historically defined for the Java platform. Code not using the new keyword is executed in default floating-point mode, which allows implementations to make better use of some processors to deliver higher performance.

    Some numeric code not marked with the strictfp keyword may behave differently in the Java 2 SDK than in previous versions. Behavior of such code may also vary between implementations of the Java platform. Overflow or underflow may occur in different circumstances and create slightly different results. These differences are not expected to have an impact on most numeric code. Code with extraordinary sensitivity to floating point behavior may be affected.

  18. In JDK 1.1 software, the syntax of expressions was extended to allow a class name to qualify a reference to a current instance using the keyword this:
    PrimaryNoNewArray: ...
    	ClassName . this
    
    The value of such an expression is a reference to the current instance of the enclosing class named ClassName, which is required to exist.

    In releases of the Java Development Kit software prior to 1.2, the javac compiler treated such expressions incorrectly, producing a reference to the current instance of the innermost enclosing class that was a subtype of the type named by ClassName. The compiler now implements such expressions properly.

    This behavior was in error, but the specification was not clear, and programmers may have relied on the incorrect behavior of the compiler.

  19. In JDK 1.1 software, the syntax of expressions was extended to allow a class name to qualify a reference to a current instance using the keyword this:
    PrimaryNoNewArray: ...
    	ClassName . this
    
    This syntax allows access to members via constructions such as:
    	
    ClassName.this.fieldname
    ClassName.this.methodname( ... )
    
    This extension was necessary because, in the presence of inner classes, there may be more than one current instance at a given point in the program. The inner classes specification neglected to include a similar extension for the super keyword:
    FieldAccess: ...
    	ClassName . super . Identifier
    
    MethodInvocation: ...
    	ClassName . super . Identifier ( ArgumentList_opt )
    

    These constructs have been implemented in the Java 2 SDK in anticipation of their inclusion in the forthcoming second edition of the JLS. In each case, the current instance is the current instance of the enclosing class named ClassName, which is required to exist.

    The following example shows how the need for the qualified super notation may arise in practice:

    class C {
        void f() { ... }
    }
    
    class D extends C {
        void f() {
        // overrides f() to run it in a new thread
            new Thread(new Runnable() {
                public void run() {
    	        D.super.f();
    	    }
    	 }).start();
        }
    }
    

    Implementation note: If an access method is necessary, it must be placed in the class named by ClassName, not in its superclass. The superclass may not necessarily be defined in the same compilation unit, and may have been compiled previously.

  20. In JDK 1.1 software, the syntax of expressions was extended to allow a constructor invocation via the keyword super to be qualified with a reference to an outer instance:
    ExplicitConstructorInvocation:  ...
    	Primary . super ( ArgumentList_opt ) ;
    
    The corresponding case for constructor invocations via this was inadvertantly ommitted:
    ExplicitConstructorInvocation:  ...
    	Primary . this ( ArgumentList_opt ) ;
    
    This construct has been implemented in the Java 2 SDK in anticipation its inclusion in the forthcoming second edition of the JLS.

  21. The Inner Classes specification does not permit an inner class to declare a member interface. This rule is enforced in the Java 2 SDK. Such declarations are silently tolerated in the JDK 1.1.x release, contrary to the specification. For example, the following program is incorrectly accepted by javac in JDK 1.1.x software, but rejected in Java 2 SDK software:
    class InnerInterface { 
        class Inner {
    	interface A { }
        }
    }
    

    A static member class is not an inner class, but is in fact a top-level class, as that term is defined by the inner classes specification. Thus, the following program, accepted by javac in both JDK 1.1.x and in the Java 2 SDK, is correct:

    class NestedInterface {
        static class Inner {
    	interface A { }
        }
    }
    

    A local class is never a top-level class, so the following example is also illegal. Both javac 1.1.x and 1.2 report a syntax error:

    class LocalNestedInterface {
        void foo() {
    	static class Inner {
    	    interface A { }
    	}
        }
    }
    

Runtime Incompatibilities in Version 1.2

  1. Virtual machines in releases prior to JDK 1.2 release will accept some class files that should, according to the VM specification, be rejected. Typically these class files have one or more of the following problems:

    1. There are extra bytes at the end of the class file;
    2. The class file contains method or field names that do not begin with a letter;
    3. The class attempts to access private members of another class; or
    4. The class file has other format errors, including illegal constant pool indices and illegal UTF-8 strings.

    The virtual machine in JDK 1.2 release has been fixed to more closely implement the specification, so it is capable of being much more strict on all of these points.

    Until the RC2 release of JDK 1.2 software this strict checking was the default behavior. During final product testing we found, however, that many existing Java applications failed to run because of some of these checks. In particular, obfuscated code frequently suffers from problems 1 and 2, while some inner-class code generated by pre-1.2 compilers suffers from problem 3. We therefore decided to relax some of these checks for the final release in order to make it as painless as possible for developers and end-users to upgrade to JDK 1.2 software.

    In a future release we expect to make the strict behavior again be the default, and between now and then we will work closely with our partners and the developer community to make sure that everyone is aware of the issues and has time to prepare for the change.

    To assist in the migration to the strict behavior we have added a new command-line option to the JDK 1.2 virtual machine: -Xfuture. This option will, in general, be used to enable behavior that we expect to become the default behavior in future releases. In JDK 1.2 software the -Xfuture option enables the strictest possible class-file format checks, access checks, and verification policies. We encourage developers to start using this option as soon as possible for all new development work. This will ensure that new Java applets and applications will be ready for the strict behavior when it becomes the default in a future release.

    The Java Plug-in always uses the strict class-file checks, as if the -Xfuture flag is set. The appletviewer ignores the -Xfuture flag and uses the more relaxed set of default checks.

  2. Prior to 1.2, simply placing code on CLASSPATH could make it more privileged. For example, pre-1.2 virtual machines would sometimes not require that some trusted class files pass verification. The details depended on the security manager installed. For example, if the following method was in a class on CLASSPATH, and was called by an applet, then it could read the user.name property:
    String getUser()
    {
      return System.getProperty("user.name");
    }
    
    This is not the case in version 1.2 of the Java Development Kit. Now such code requireds a call to doPrivileged:
    String getUser()
    { 
       return(String)
         java.security.AccessController.doPrivileged(new PrivilegedAction() {
             public Object run() {
                 return System.getProperty("user.name");
             }
         });
    }
    

  3. In versions 1.0 and 1.1 of the JDK software, the runtime system would finalize objects, that is, invoke their finalize methods, somewhat aggressively. Though those earlier platforms employed a low-priority thread to finalize objects, in some situations all finalizable but unfinalized objects would be finalized directly by the garbage collector at the end of nearly every garbage-collection cycle. Code written for such systems may unintentionally depend upon this prompt GC-invoked finalization for correct operation, which can lead to complicated bugs and deadlocks.

    The situation is improved in version 1.2 because finalization is not performed directly by the garbage collector; instead, objects are finalized only by a high-priority thread. This means that, in a busy program, the time between the moment when object becomes finalizable and the moment when it is actually finalized may be longer than with previous versions of the runtime system.

    In JDK software version 1.2, the runtime system properly implements the definition of finalization in the Java Language Specification, so this difference is not, strictly speaking, an incompatibility. This change may, however, cause programs to malfunction if they rely upon prompt finalization. Many such programs can be repaired by using reference objects instead of finalize methods. (Reference objects are implemented by the java.lang.ref.Reference class and its subclasses.) A less preferable workaround is to periodically invoke the Runtime.runFinalization method at regular intervals.

  4. In version 1.2 of the Java Development Kit, an unimplemented abstract method or interface method will cause an AbstractMethodError to be raised at run time when the method is invoked. In previous versions, the error occurred during link time.

  5. The security model in version 1.2 of the Java platform changes the way in which resources are accessed. When a security manager is in force, resources must reside at a URL that has been granted appropiate security permissions by a policy file. The default policy file, java.policy, grants all security permissions to resources located in the lib/ext directory, where extensions stored. The default policy file is located at <java.home>/lib/security/java.policy.

    In addition, an invocation to access system resources, as for example by ClassLoader.getResource, must be enclosed within an AccessController.doPrivileged call. Attempts to access system resources without use of a doPrivileged statement will fail. This is true even if the resources that are granted security permissions by the policy file.

  6. Prior to the JDK 1.1.6 software, the name of the default ISO 8859-1 character encoding in the was "8859_1". Since the JDK 1.1.6 software, the name has changed to "ISO8859_1". The old name "8859_1" continues to work when passed as an argument to methods in the API, but does not work when used in font.properties files.

  7. Each of the following classes in package java.util.zip has a constructor that accepts an int parameter to specify the buffer size:
    DeflaterOutputStream
    InflaterInputStream
    GZIPInputStream
    GZIPOutputStream
    
    In the 1.2 platform, an IllegalArgumentException is thrown if the input parameter for buffer size is less than or equal to 0. In the 1.1 platform, these constructors do not throw IllegalArgumentException if the size parameter is less than or equal to 0.

  8. When the 1.2 Java virtual machine attempts to load a class file that is not of the proper class file format, a java.lang.ClassFormatError is thrown. A java.lang.UnsupportedClassVersionError is thrown when the virtual machine attempts to load a class file which is not of a supported major or minor version. Earlier versions of the virtual machine threw java.lang.NoClassDefFoundError when either of the above class file problems was encountered.

  9. In the Java 2 SDK, application classes are loaded by an actual ClassLoader instance. This makes it possible for application classes to use installed extensions and also separates the application class path, which is specified by the user, from the bootstrap class path, which is fixed and normally should not be modified by the user. The -Xbootclasspath option can be used to override the boostrap class path if necessary.

    However, this means that in 1.2, application classes no longer have all permissions by default. Instead, they are granted permissions based on the system's configured security policy. This may cause some applications that write their own security code based on the original security model in 1.0/1.1 to throw an exception and not start in 1.2. A workaround is to run these applications with the oldjava application launcher, which is documented on the reference page for the java application launcher.

    See the document Command Line Changes From 1.1 to 1.2 for more information. The document can be found in the documentation download at docs/tooldocs/solaris/migration.html.

    See the extension mechanism specification for more information regarding the new extension mechanism and its effect on class loading. The document provides relevant information regarding the new class loader delegation model and class loader API changes and can be found in the documentation download at docs/guide/extensions/spec.html.

    See the JDK security documentation for information regarding the security model of version 1.2 of the Java platform. The documention can be found in the documentation download at docs/guide/security.

  10. In the Java 2 SDK, the constructors of some classes in package java.io check for null input parameters. Such checks were not performed in earlier versions of the platform.
    • The constructors PrintStream(OutputStream out) and PrintStream(OutputStream out, boolean autoFlush) will throw a NullPointerException if parameter out is null.
    • Similar checks have also been added in the Java 2 SDK to constructors InputStreamReader(InputStream in) and InputStreamReader(InputStream in, String enc). These constructors throw NullPointerException if parameterin is null.
    • In the Java 2 SDK, the constructors Reader(Object lock) and Writer(Object lock) now throw NullPointerException if parameter lock is null.

  11. In JDK 1.1 software, Thread.stop is able to interrupt a thread blocked in Object.wait or Thread.sleep. However, in Java 2 SDK software running on the Solaris 2.6 operating environment with native threads, Thread.stop cannot interrupt a blocked thread. The Java 2 SDK behaves the same as the JDK 1.1 release with respect to Thread.stop when running on other operating systems or on Solaris 2.6 operating platform with green threads.

  12. Version 1.2.2 of the Java 2 SDK contains a revised class-loading mechanism. Under the new class loader, if any class file belonging to a package in a Jar file is signed, all class files belonging to the same package must have been signed by the same signers. It is no longer possible to use a Jar file in which some classes of a package are signed and others are unsigned or signed by a different signer. Jar files may still contain packages that are unsigned. However, if any packages contain signed classes, all class files of that package must be signed by the same signer. Existing Jar files that don't meet this criterion will not be usable with version 1.2.2 of the Java 2 SDK or Runtime Environment.

  13. Foreground and background colors of native components may bet set explicitly using the setForeground and setBackground methods. If the colors are not set explicitly, default colors are used as follows:
    • In version 1.2 and later of the Java 2 platform, default colors of native components are taken to be the colors defined by the underlying operating system.
    • Prior to version 1.2, default colors were pre-defined by the Java platform itself.
    Code compiled with 1.1 that relies on the default colors can exhibit different and sometimes undesireable component appearance when run on a 1.2 platform. For example, if the 1.1 code explicitly sets the forground color to white for a component label but uses the default background color, the label will not be visible when run on 1.2 if the underlying operating system's default background color is white.

API Incompatibilities in Version 1.2

  1. The Project Swing and Accessibility packages, formerly in the com.sun.java.* namespace, have moved to the javax.* namespace. These packages now have the following names:
    • javax.swing
    • javax.swing.border
    • javax.swing.colorchooser
    • javax.swing.event
    • javax.swing.filechooser
    • javax.swing.plaf
    • javax.swing.plaf.basic
    • javax.swing.plaf.metal
    • javax.swing.plaf.multi
    • javax.swing.table
    • javax.swing.text
    • javax.swing.text.html
    • javax.swing.tree
    • javax.swing.undo
    • javax.accessibility

    Applications that use the old com.sun.java.swing* names for these packages from Project Swing 1.0 software will not work in the 1.2 platform. Such applications should be updated to use the new java.swing package names. A PackageRenamer tool for making this conversion is available online.

    Note that packages com.sun.java.swing.plaf.windows and com.sun.java.plaf.motif have not changed names.

    If necessary, you can force applications using the old package names to work on the 1.2 platform by placing the Project Swing 1.0 jar file first on the boot class path:

    java -Xbootclasspath:<path to 1.0 swingall.jar>:<path to 1.2 rt.jar> ...
    

    Note that the Project Swing package which is bundled with the Java 2 SDK software has some modifications to deal with 1.2 Security. Therefore if the above technique (-Xbootclasspath) is used to run the Project Swing 1.0 classes with Java 2 SDK in an environment where a security manager is present (i.e. applets in a browser), then the program may not run correctly.

  2. The stringFlavor and plainTextFlavor fields of class java.awt.datatransfer.DataFlavor have been made final in version 1.2 of the Java platform:
    public static final DataFlavor stringFlavor
    public static final DataFlavor plainTextFlavor
    
    In version 1.1 of the Java platform, these fields were not final.

  3. Interface java.util.List has been added to version 1.2 of the Java platform. Existing source code may now produce a namespace conflict between java.awt.List and java.util.List.

    In version 1.2 of the Java Development Kit, using the 'wildcard' import statements

    import java.awt.*;
    import java.util.*;
    
    together will cause a compiler error for code that contains the unqualified name List. This problem can be worked around in either of two ways. One way is to add an import statement such as
    import java.awt.List;
    
    to resolve the conflict throughout the file. An alternate solution is to fully qualify the class name by the desired package at each point of use.

    A similar issues exists with regard to java.io.FileFilter and javax.swing.filechooser.FileFilter. Both of these were introduced into the Java platform in version 1.2.0. However, the Swing FileFilter class was available to JDK 1.1 users as part of the Swing optional package. JDK 1.1 users that were using the Swing FileFilter class will need to fully qualify references to java.io.FileFilter and javax.swing.filechooser.FileFilter their code in order to run on J2SE 1.2.0.

  4. In version 1.2 of the Java Development Kit, the field CHAR_UNDEFINED in class java.awt.event.KeyEvent has the value 0xffff. In versions 1.1.x, the field had a value of 0x0. This change was made because 0 is a valid Unicode character and therefore cannot be used to define CHAR_UNDEFINED. Prior to version 1.2, there was no way to detect the difference between a valid Unicode null character and a KeyEvent.CHAR_UNDEFINED.

  5. In version 1.2 of the Java platform, the signature of the java.io.StringReader.ready method has been changed to allow an IOException to be thrown if the StringReader has been closed. This change was required (bug 4090254) in order to make the StringReader class properly implement the general contract spelled out in the abstract class java.io.Reader, which it extends.

  6. In version 1.2, the specifications for Integer.decode() and Short.decode() are explicit about the correct representation of negative numbers. Negative numbers always begin with a minus sign (-). If the number is hexadecimal or octal, the base specifier (0x, #, or 0), must come after the minus sign.

    In version 1.1, the specifications did not clearly state whether a minus sign should come before or after a base specifier. The actual implementations of Integer.decode() and Short.decode() expected the base specifier, if any, to come before the minus sign, if any.

    For example, in 1.2 decoding "-0x5" returns negative 5 and decoding "0x-5" throws a NumberFormatException. In 1.1, the results were exactly opposite: "-0x5" threw a NumberFormatException and "0x-5" returned negative 5.

    The decoding rules used in 1.1 were unconventional and undocumented. However, some programs may rely on this behavior.

  7. In Java 2 Platform, classes java.util.Vector and java.util.Hashtable have been retrofitted to implement the relevant interfaces in the new Collections Framework ( java.util.List and java.util.Map, respectively). As a consequence, the semantics of the equals and hashCode methods have changed to provide value equality, rather than reference equality, as per the general contracts set forth in List.equals and Map.equals.

    This raises several compatibilility issues:

    1. "Self-reference" (inserting a Vector or Hashtable into itself) can now cause stack overflows under certain circumstances:
      • If a Hashtable is inserted into itself as a key, the Hashtable becomes corrupt, and subsequent operations may cause stack overflow. (It has never been permissible to mutate an object that is serving as a Hashtable key. Inserting an object into a Hashtable now qualifies as mutation, since it affects equals comparison.)
      • If a Hashtable contains itself as a value (AKA element), equals and hashCode are undefined by the contract. If the hashCode or equals methods are called on such a "self-referential" Hashtable, a stack overflow may result.
      • If a Vector contains itself as an element, equals and hashCode are undefined by the contract, and may cause a stack overflow.
    2. Because equals and hashCode now depend on the contents of the Vector or Hashtable, they are now synchronized against other operations on the collection. Prior to the Java 2 Platform, they were unsynchronized. The additional synchronization could cause liveness problems if a client depended on the fact that equals or hashCode were unsynchronized.
    3. Clients with explicit dependence on the "reference equality" behavior of equals for Vector or Hashtable will not operate properly. For example, suppose a program kept a Hashtable whose keys were all of the Vectors (or Hashtables) in some system. It was previously the case that each Vector (or Hashtable) was a distinct key, regardless of its contents. It is now the case that any two Vectors (or Hashtables) with the same contents are considered equal. Further, it is no longer legal to modify a Vector or Hashtable that is currently serving as the key in a Hashtable.
    4. Because equals and hashCode now examine the entire contents of the Vector or Hashtable, they may run more slowly than they used to for large collections.

  8. The java.io.File class has been more precisely specified in version 1.2 of the Java platform. File is now a true abstract representation of file and directory pathnames. These changes allow the File class to better support non-Unix platforms such as Windows, which has a rich pathname syntax involving drive letters, UNC share names, and multiple separator characters. The original specification could not handle these cases because it was written in terms of simple string operations. [Bugs 4131169, 4102262, 4103608, 4123637, 4040846]

    The new version of the File class is compatible with both its originally intended behavior and its current common uses. However, some minor differences in behavior may cause some programs to fail.

    • When converting a String into an abstract pathname, the new version of the File class translates all separator characters into the default separator character for the platform, as defined by the system property file.separator. This makes no difference on Unix systems, which support only one separator character. Windows systems, however, support the two distinct separator characters '/' and '\\', with '\\' being the default. On Windows systems, therefore, the expression
            new File("foo/bar").getPath() 
      now evaluates to the string "foo\\bar".

    • The new version of the File class also removes redundant separator characters, including those at the end of a pathname string. Thus the expression
            new File("foo//bar/").getPath() 
      evaluates to the string "foo/bar" on a Unix system and "foo\\bar" on a Windows machine.

  9. In the Java 2 SDK, the checkAccess method of java.lang.Thread is final. In the 1.1 platform, checkAccess was not final. [Bug 4151102]

  10. In the 1.2 platform, the getInterfaces method of class java.lang.Class will return an array containing Cloneable and Serializable class objects when invoked on a class representing an array. In the 1.1 platform, getInterfaces returned an empty array when invoked on the class representing an array.

  11. In the 1.2 platform, abstract classes java.text.BreakIterator, java.text.SimpleTextBoundary, and java.text.Collator (and Collator's subclass java.text.RuleBasedCollator) no longer implement the Serializable interface as they did in the 1.1 platform. [Bug 4152965]

  12. In the Java 2 SDK, abstract method drawString(AttributedCharacterIterator, int, int) has been added to class java.awt.Graphics as part of the Input Method Framework for use by the PersonalJava platform. It is expected that suclasses of Graphics in applications based on the 1.1 platform are rare. Any such subclasses that do exist, however, will need to provide an implementation of this new abstract method for use in conjunction with the 1.2 platform. [bug 4128205]

  13. The String hash function implemented in 1.1 releases did not match the function specified in the first edition of the Java Language Specification, and was, in fact, unimplementable. Additionally, the implemented function performed very poorly on certain classes of strings, including URLs.

    To bring the implementation into accord with the specification, and to fix the performance problems, the new String hash function in version 1.2 is:

         s[0] * 31^(n-1) + s[1] * 31^(n-2) + ... + s[n-1]
    
    where s[i] is the ith character of string s.

    This change should have no effect on the overwhelming majority of applications. If an application has persistent data that depends on actual String hash values, it could theoretically be affected, but the serialized representation of a Hashtable does NOT depend on the actual hash values of the keys stored in the Hashtable. Thus, applications relying on serialization for storage of persistent data will be unaffected. [Bug 4045622]

  14. Developers are strongly encouraged to migrate native methods to JNI. JNI is the standard way for making your native libraries interoperate with the Java programming language, and JNI offers virtual machine independence for any native code that you might write. Some virtual machine implementations may continue to support NMI while other may not.

  15. This section describes compatibility issues affecting developers who implement the interfaces in the java.sql package. Developers in this group consist primarily of persons implementing JDBC drivers. If you do not implement the interfaces defined in the java.sql package in your code, the issues discussed in this section will not affect you.

    The following interfaces contain new methods in the Java 2 SDK:

      java.sql.Connection java.sql.DatabaseMetaData java.sql.ResultSetMetaData java.sql.ResultSet java.sql.CallableStatement java.sql.PreparedStatement java.sql.Statement

    Source code which implements the JDK 1.1 versions of these interfaces will not compile properly under the Java 2 SDK unless it is changed to implement the new methods. In addition, the following interfaces support types that are new in the Java 2 SDK:

      java.sql.ResultSet java.sql.CallableStatement java.sql.PreparedStatement

    Source code that implements these interfaces and compiles correctly in the Java 2 SDK will fail to compile under the JDK 1.1 software since the new types added to java.sql are not present in the JDK 1.1 release.

  16. A public field, serialVersionUID, was introduced into the java.io.Serializable interface in Java 2 SDK, Standard Edition, v1.2. This field should never have been introduced into the interface. Its meaning is unspecified, and its presence contradicts the java.io.Serializable specification.

    The API specification for java.io.Serializable states

    "The serialization interface has no methods or fields."

    Furthermore, according to the serialization specification, the only way to get the serial version UID of a class is through the ObjectStreamClass.lookup(className).getSerialVersionUID() method. It does not make sense to try to get the serial version UID through a field that might or might not exist.

    The serial version UID is sometimes computed and sometimes explicitly defined in a class, but it is never inherited from a superclass or interface. Since interfaces cannot be instantiated directly, a serialVersionUID field in an interface can be of no use to the serialization system. In fact, the serialization system makes no use of this field.

    For these reasons, the public serialVersionUID field was removed in version 1.2.2 of the Java 2 SDK. It is expected that this change will not break any existing applications.

  17. Classes such as Point and Dimension now implement special Java2D interfaces (Point2D and Dimension2D respectively). This adds methods, such as getHeight in the case of Dimension, that return type double. These classes currently provide public variables of type int. When using JavaBeans style introspection on one of these classes under 1.1, you would find properties of type int. You will now find these typed as double. This may cause issues for programs which make specific assumptions on the types supported by the properties in question.

Serialization Incompatibilities in Version 1.2

  1. Because of rare and infrequent problems with the format for Externalizable objects, it was necessary to make an incompatible change in the Java 2 SDK. A 1.1.5 (or earlier) program will throw a StreamCorruptedException when it tries to read an Externalizable object generated in version 1.2's new format. Programs based on JDK software version 1.1.6 or later do not have this problem.

    A new API in 1.2 supports backward compatibility. To write streams in the old format, call

    	ObjectOutputStream.useProtocolVersion(PROTOCOL_VERSION_1) 
    before doing any writes.

  2. If a serializable class has methods with names starting with the '$' character, then the computation of the serial version UID will be different in versions 1.1 versus 1.2 due to changes in the computation algorithm.

    Hence a serialized stream of such a class generated in one version cannot be deserialized in the other version, because the serial version UID will be computed differently for this class in the other version.

  3. In the JDK 1.1 release, serialization explicitly uses the access modifiers associated with the static initialization method of classes (<clinit>) as one of the components in the computation of the serial version UID. The spec is unclear about what the access modifiers for such methods should be and just states that the VM ignores it. As a result it is possible to have a legal class file format where the access modifier for the <clinit> method could be anything!! Thus in 1.1, serial version UIDs computed for the same class could be different, depending on the compiler used to generate the class file.

    Further in 1.2 the serial verison UID computation algorithm was changed to explicitly use STATIC as the access modifier for the <clinit> method, ignoring the actual access modifier for this method in the class file. This causes an incompatibility between versions 1.1 and 1.2 for such systems where the class files are generated with a access modifier other than STATIC (such as STATIC+PUBLIC) for their static initialization methods <clinit>.


*As used on this web site, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform.