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.
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.
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.
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.
- 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)
- 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';
- 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)
- ''' (and therefore '\u0027') is not a legal char literal and will not be
passed by the 1.2 compiler. Use '\'' instead. (Bug 1265387)
- \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.
- The type void[] is not legal and will not be passed by
the 1.2 compiler. (Bug 4034979)
- It is not legal to combine the abstract method modifier with
private, final, native, or synchronized modifiers. (Bug 1266571)
- 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)
- 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)
- 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;
}
}
|
- 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);
- 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.
- 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.
- 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.
- 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;
}
}
|
- 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.
- 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.
- 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.
- 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.
- 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.
- 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
- 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:
- There are extra bytes at the end of the class file;
- The class file contains method or field names that do not begin with a
letter;
- The class attempts to access private members of another class; or
- 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.
- 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");
}
});
}
|
-
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.
- 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.
- 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.
- 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.
- 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.
- 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.
-
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.
-
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.
-
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.
-
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.
-
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
-
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.
- 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.
- 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.
- 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.
-
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.
-
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.
- 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:
-
"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.
- 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.
- 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.
- 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.
-
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.
-
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]
-
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.
-
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]
-
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]
- 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]
- 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.
- 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.
- 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.
- 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
-
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.
- 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.
- 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.
|