Compatibility is a complex issue. This document discusses three types of potential incompatibilities relating to a release of the Java platform:
For more information, see Kinds of Compatibility, a section in the OpenJDK Developer's Guide.
The following compatibility documents track incompatibility between adjacent Java versions. For example, this compatibility page reports only Java SE 7 incompatibilities with Java SE 6, and not with previous versions. To examine Java SE 7 incompatibilities with earlier Java versions, you must trace incompatibilities through the listed files, in order.
The following documents have information on changes to the Java Language Specification (JLS) and the Java VM Specification (JVMS).
Java SE 7 is binary-compatible with Java SE 6 except for the incompatibilities listed below. Except for the noted incompatibilities, class files built with the Java SE 6 compiler will run correctly in Java SE 7.
The class file version for Java SE 7 is 51, as per the JVM Specification, because of the invokedynamic
byte code introduced by JSR 292. Version 51 class files produced by the Java SE 7 compiler cannot be used in Java SE 6.
Java SE 7 includes new language features and platform APIs. If these are used in a source file, that source file cannot be compiled on an earlier version of the Java platform.
In general, the source compatibility policy is to avoid introducing source code incompatibilities.
Deprecated APIs are interfaces that are supported only for compatibility with previous releases. The javac
compiler generates 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 APIs, although there are no current plans to remove such APIs 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.
In its simplest form, behavioral compatibility means that with the same inputs a program performs the same (or an equivalent) operation under different versions of libraries or the platform. There are aspects of the platform's behavior that are intentionally unspecified and the underlying implementation may change in a platform release. For this reason, it is recommended that code is written in such a way so that it does not depend on unspecified behavior: In this scenario, the problem is not an incompatibility in the platform, is it a bug in the code.
Java SE 7 is strongly compatible with previous versions of the Java platform. Almost all existing programs should run on Java SE 7 without modification. However, there are some minor potential source and binary incompatibilities in the JRE and JDK that involve rare circumstances and "corner cases" that are documented here for completeness.
StackMapTable
attributes when appropriate. For classfiles with version 50, the Hotspot JVM would (and continues to) failover to the type-inferencing verifier if the stackmaps in the file were missing or incorrect. This failover behavior does not occur for classfiles with version 51 (the default version for Java SE 7).
Any tool that modifies bytecode in a version 51 classfile must be sure to update the stackmap information to be consistent with the bytecode in order to pass verification.
class Foo extends Exception {}
class SonOfFoo extends Foo {}
class DaughterOfFoo extends Foo {}
...
try {
throw new DaughterOfFoo();
} catch (final Foo exception) {
try {
throw exception; // used to throw Foo, now throws DaughterOfFoo
} catch (SonOfFoo anotherException) { // Reachable? }
}
throw exception;
statement throws a Foo
exception in JDK 6, but throws a DaughterOfFoo
exception in Java SE 7.
The second incompatibility is that the catch (SonOfFoo ...)
statement compiled under JDK 6 but, under Java SE 7, gets the following error:
error: exception SonOfFoo is never thrown in body of corresponding try statement
MirroredTypeException
is now a subclass of MirroredTypesException
javax.lang.model.type
package, MirroredTypeException
and MirroredTypesException
, were unrelated. In the javac
implementation, MirroredTypeException
was thrown where MirroredTypesException
should have been thrown. In part to address this problem, MirroredTypeException
was made a subclass of MirroredTypesException
. This change is binary compatible and generally preserves the behavior of existing annotation processors. However, it is possible this change may cause source incompatibilities for client programs; in those cases, changing the order of catch clauses should allow the programs to compile again.
TypeVisitor
interface has been updated
javax.lang.model.*
including adding a method to the javax.lang.model.type.TypeVisitor
interface. Such an addition is source incompatible with libraries that have directly implemented the TypeVisitor
interface. However, such additions were foreseen as part of this API's evolution and libraries were explicitly cautioned to extend one of the utility visitors instead of directly implementing such an interface.
java.lang.Float.parseFloat(String)
and parseDouble(String)
Updated to Document Exception
java.lang.Float.parseFloat(String)
and java.lang.Float.parseDouble(String)
methods have been throwing an undocument NullPointerException
when passed a null argument since the methods were introduced in J2SE 1.2. The spec has been updated to document the NPEs.
java.lang.Character.isLowerCase/isUpperCase
Methods Are Updated to Comply with the Specified Unicode Definition
isLowerCase
and isUpperCase
methods have been updated to comply with the Unicode Standard definition to be GD=Lu/Ll + Other_UpperCase/LowerCase
. Two new methods, java.lang.Character.isAlphabetic(int)
and java.lang.Character.isIdeographic(int)
have also been added.
java.util.TreeMap
, it was previously possible to insert invalid null elements and elements not implementing the Comparable
interface into an empty TreeMap
or TreeSet
. Only a single invalid element could be inserted into an empty TreeMap
or TreeSet
; additional elements would cause the expected NullPointerException
or ClassCastException
. Most other operations upon the collection would also fail. As of Java SE 7, inserting an invalid null element or an element not implementing Comparable
into an empty TreeMap
or TreeSet
throws a NullPointerException
.
Formatter.format()
Now Throws FormatFlagsConversionMismatchException
Formatter.format(String,Object...)
method now throws a FormatFlagsConversionMismatchException
exception when the "#" flag is specified for conversion "s" and the following argument is not a Formattable
instance (including the special case "null").
java.nio.channels.DatagramChannel
Methods have Changed
DatagramChannel
is the selectable channel for datagram-oriented sockets in the java.nio.channels
package. The behavior for the send
, receive
, and connect
methods have been modified. To restore the previous behavior, the sun.nio.ch.bugLevel
property can be set to the value of "1.4", "1.5", or "1.6". See the DatagramChannel
class specification for more information.
java.nio.channels
package may encounter a source code incompatibility with the Java SE 7 release. See the API specification for more information.
java.awt.Color
Method Documents Potential Exception
java.awt.color.ICC_Profile.setData(int, byte[])
method to throw an exception, but the exception and the conditions under which it was thrown, was not documented. The specification has been updated.
MouseEvent.getButton()
method may return values outside of the [0-3] range
MouseEvent.getButton
method returned a value between 0 and 3 when the user clicked a button or used the scroll wheel. To accommodate newer models of mice with two scroll wheels, or four and five buttons, the method now returns a value from 0 to the number of buttons. This may cause problems for code that expects a value from 0 to 3. Setting the sun.awt.enableExtraMouseButtons
property to false restores the JDK 6 behavior.
Windows.setBackground
may result in an UnsupportedOperationException
exception
Windows.setBackground()
method. Setting the background to a non-opaque color results in making the window per-pixel translucent. However, some systems may not support this visual effect, and as such invoking the setBackground()
method with a non-opaque color will result in an UnsupportedOperationException
exception.
This does not affect new applications that set a non-opaque color deliberately because the code should first verify that the effect is supported by invoking the GraphicsDevice.isWindowTranslucencySupported
method. However, legacy applications that apply a non-opaque background color to their frames may fail when the application is run on a system that doesn't support translucency effects. We hope that this will not affect too many legacy applications because a) there are few (if any) legacy apps that apply a non-opaque background color to their frames, and b) most modern systems support tranclucency effects.
Toolkit.getPrintJob(Frame, String, Properties)
now throws NullPointerException
Toolkit.getPrintJob(Frame, String, Properties)
in a headless environment, a HeadlessException
is thrown instead of the specified NullPointerException
. As of the Java SE 7 release, a NullPointerException
is thrown in this situation.
sun.awt.exception.handler
System Property has Been Replaced with Official API
sun.awt.exception.handler
system property should be rewritten to use the standard exception handling mechanism. See the Thread.UncaughtExceptionHandler
class for details.
com.sun.image.codec.jpeg
Package is Retired
com.sun.image.codec.jpeg
package was added in JDK 1.2 (Dec 1998) as a non-standard way of controlling the loading and saving of JPEG format image files. This package was never part of the platform specification and it has been removed from the Java SE 7 release. The Java Image I/O API was added to the JDK 1.4 release as a standard API and eliminated the need for the com.sun.image.codec.jpeg
package.
final
final
at the time.
Path2D.Double.getPathIterator(AffineTransform)
Path2D.Float.getPathIterator(AffineTransform)
Path2D.getPathIterator(AffineTransform flatness)
final
in Java SE 7. Subclasses that tried to override these methods will fail to link in Java SE 7 or later.
Locale.getDefault(Locale.Category)
method takes a Locale.Category
parameter. Previous behavior can be restored by setting the sun.locale.formatasdefault
system property to true
.
Map
supplied when creating the Connector Server. See the javax.management.event
package documentation for more information.
readonly
and readwrite
. The readwrite
access control now has a new create
keyword that lists the MBean
classes that can be created. The access control from out-of-the-box management is also available programmatically, through the configuration item jmx.remote.x.access.file
in the Map
argument passed to JMXConnectorServerFactory.newJMXConnectorServer
. For the rare case of users who use simplified access control and then create MBeans
remotely, such applications can be fixed without recompiling: all that is needed is to change the contents of the access control file.
RowSetFactory
Interface to allow Creation of a RowSetFactory
RowSetFactory
. As part of this update, the definition of some constants has changed slightly, but should not affect most users.
java.sql.Connection
, java.sql.Driver
, javax.sql.CommonDatasource
, and java.sql.Statement
interfaces. Because all methods of an interface must be implemented, previous code that uses these interfaces will not compile on Java SE 7 unless you add the new methods. See the JDBC documentation for more information.
javac
, in HotSpot, or Java SE APIjava.lang.Class
changed the fixed order in which they return the methods and constructors of a class:
getMethods
getDeclaredMethods
getDeclaredConstructors
class Test {
<Z> List<Z> m(List<? super Z> ls) { return null; }
void test(List<String> ls) {
List<Integer> i = m(ls);
}
}
This program compiles in JDK 6 - inferring Integer
for the type-variable Z. Now, if you replace Integer for Z in the declaration of 'm' [this leads to m(List<? super Integer>)]
, it is easy to spot that the method should not be applicable, as we are attempting to pass a List<? super String>
where a List<? super Integer>
is expected. This is a violation of the type-system rules, and eventually, will lead to heap pollution (see the JLS, Java SE 7 Edition, section 4.12.2.1) - that is why the JDK 7 compiler rejects the code.
class Test {
<Z extends List<Z>> List<Z> m() { return null; }
void test() {
List<?> i = m();
}
}
Test.java:7: incompatible types; inferred type argument(s)
java.lang.Object do not conform to bounds of type variable(s) Z
found : <Z>java.util.List<Z>
required: java.util.List<?>
List<?> i = m();
^
1 error
class Test<X extends Test<X>> {
Test<?> t = new Test<>();
}
class X<Y extends Integer> {
class Y {}
class Y1<T extends X<Y>> { }
}
Y
inside the Y1
declaration is resolved as X.Y
and, since X.Y
is not a subtype of Integer
, the JDK 7 javac
compiler reports an error.
class A {
int m(List<String> ls) { return 0; }
long m(List<Integer> ls) { return 1; }
}
javac
has been fixed so that it correctly implements the check described in the JLS, Java SE 7 Edition, section 8.4.8 and 9.4.1. This check states that a class may not contain two methods whose erased signatures are identical, even when those methods are not override-equivalent. This restriction, due to limitations of the type-erasure technique used by javac
to translate generics, was not implemented properly in javac
. As a result, there were some cases in which javac
detected the problem, while there were other cases in which javac
did not detect the problem. As a result of this fix, the checks described in 8.4.8 and 9.4.1 are now properly implemented, resulting in a slightly stricter javac
behavior.
For instance, the following code is legal prior to JDK 7:
class A{
public int compareTo(Object o){
return 0;
}
}
class B extends A implements Comparable<B> {
public int compareTo(B b){
return 0;
}
}
javac
, on the basis that B
contains two methods, compareTo(X)
(indirectly overridden by Comparable<B>.compareTo(B))
and compareTo(Object)
(from A
) that are not override-equivalent, but whose erased signature is identical.
javac
compiler has been fixed in how it selects the most specific varargs method when more than one method is applicable to a given call-site (see the JLS, Java SE 7 Edition, section 15.12.2.5). Because of a bug, both JDK 5.0 and JDK 6 compilers reject the following legal code:
class Test {
void foo(int... i) {}
void foo(double... d) {}
void test() {
foo(1,2,3);
}
}
In the above example, both methods are applicable (because you can pass an int
where a double
is expected). Since both methods are applicable, the compiler must select the so-called most-specific method, that is, the best candidate among the two. This is done by looking at the signatures of both methods; in this case, since one method (foo(double...))
is accepting an argument that is more general than the other (foo(int...))
, the answer is straightforward: the most specific method is foo(int...)
.
While the javac
compiler accepts more code than it did prior to JDK 7, this fix also results in a slight source incompatibility in the following case:
class Test {
void foo(int... i) {}
void foo(Object... o) {}
void test() {
foo(1,2,3);
}
}
This code compiles in JDK 6 (the most specific method is foo(int...))
. This code does not compile under JDK 7. As per 15.12.2.5, it is not possible to choose between foo(int...)
and foo(Object...)
as neither int
is a subtype of Object
, nor Object
is a subtype of int
. This program should be disallowed (in fact, it should never have been allowed in the first place).
public abstract class Test implements Iterable<Class>, Iterable<Class&g
t; {}
public interface Test extends Iterable<Class>, Iterable<Class> {}
public abstract class Test<T extends Iterable<Class> & Iterable<
Class>> {}
javac
erroneously allowed access to private members of type-variables. This is wrong, as the JLS, Java SE 7 Edition, section 4.4, states that the members of a type-variable are the members of an intersection types whose components are the type-variable bounds (intersection types are defined in section 4.9) - and intersection types do not inherit private members from their components. As a result, the following program should get a compilation error:
class A {
private int val = 42;
}
class Test<X extends A> {
void test(X x) {
int i = x.val; //error in JDK 7
}
}
The above program compiles in JDK 6. Note that accepting this program is inherently unsound; there is no guarantee that X
will be instantiated to a type that inherits val
. For instance, if we called test()
on an instance whose type is Test<B>
, where B
is a subclass of A
, val
should not be accessible there. Since javac
cannot guarantee the well-formedness of this program for all possible instantiations of X this program must be rejected.
class Outer<X> {
static class Inner {}
}
Outer<String>.Inner
apt
Tool has been Decommissioned
apt
functionality has been superceded by standardized annotation processing in JSR 269. Running the apt
tool in JDK 7 prints a warning that it will be removed in the next major release.
java.vendor = Sun Microsystems Inc.
java.vendor.url = http://oracle.com/technetwork/java/
java.vm.vendor = Sun Microsystems Inc.
java.specification.vendor = Sun Microsystems Inc.
java.vm.specification.vendor = Sun Microsystems Inc.
java.vendor = Oracle Corporation
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
java.specification.vendor = Oracle Corporation
java.vm.specification.vendor = Oracle Corporation
com.sun.management.jmxremote.local.only
, when true (the default) indicates that the local JMX RMI connector will only accept connection requests from local interfaces. Setting this property to false restores JDK 6 behavior, but is not recommended because the local JMX RMI connector server will accept connection requests from both local and remote interfaces. For remote management, the remote JMX RMI connector server should be used with authentication and SLL/TLS encyrption enabled.
javax.management.Objectname
class and javax.management.MBeanServerDelegate.getImplementationVendor
and javax.management.MBeanServerDelegate.getSpecificationVendor
methods have been modified to return strings that identify Oracle as the default implementation vendor for JMX, rather than "Sun Microsystems."
XSLTProcessorApplet
Class is Removed
XSLTProcessorApplet
class is an application-level convenience class that had various problems. It has been removed from the JDK 7 release.
SOAP Message Construct, the XML infoset of a SOAP message MUST NOT contain a document type declaration (DTD) information item.
IllegalArgumentException
java.util.Arrays.sort
and (indirectly) by java.util.Collections.sort
has been replaced. The new sort implementation may throw an IllegalArgumentException
if it detects a Comparable
that violates the Comparable
contract. The previous implementation silently ignored such a situation.
If the previous behavior is desired, you can use the new system property, java.util.Arrays.useLegacyMergeSort
, to restore previous mergesort behavior.
ThreadGroup.setMaxPriority
Method Now Behaves as Specified
ThreadGroup.setMaxPriority
did not behave as specified if the passed-in value was less than Thread.MIN_PRIORITY
: it reset the input value to Thread.MIN_PRIORITY
. The specification states that a value less than Thread.MIN_PRIORITY
will be ignored. The method now behaves as specified.
java.io.File.setReadOnly
and setWriteable
Methods Have New Behavior
java.io.File
setReadOnly
and setWritable
methods no longer set the DOS readonly attribute on directories. This means that these methods will fail, by returning false, if the file is a directory. To preserve the relationship with canWrite
, the canWrite
method returns true if the file is a directory.
Applications that want to set directories on Windows to be read only must use the new API. In particular, the Files.isWritable
method takes into account the effective access (as determined by the file's discretionary access control list) and whether the file is located on a writable volume.
http
Response Code is -1
IOException
. For example, the following code is problematic:
public static void test () throws Exception {
.....
HttpURLConnection urlc = (HttpURLConnection)url.openConnection();
....
System.out.println ("Response code: " + urlc.getResponseCode());
/** Following line throws java.io.IOException: Invalid Http response
* when Response Code returned was -1
*/
InputStream is = urlc.getInputStream(); // PROBLEMATIC CODE
getResponseCode
method and deal with a -1
value appropriately; perhaps by opening a new connection, or invoking getErrorStream
on the stream.
javax.swing.text.ParagraphView.Row
Package-Private Class is Removed
javax.swing.text.ParagraphView.Row
class has been removed. This class was intended for internal use only and, in the remote chance that an application uses this class, it will fail.
java.text.BreakIterator.isBoundary(int)
Method Now Behaves as Specified
java.text.BreakIterator.isBoundary(int)
method now returns false
, as specified, when the given offset is out of bounds, rather than throwing an IllegalArgumentException
.
This affects any existing BreakIterator
implementations in the following cases:
BreakIterator
implementations that don't override the default isBoundary
implementation will see behavior change with the BreakIterator.last+1
value. That is, any applications that include a customized BreakIterator
implementation with the default isBoundary
will see the behavior change in JDK 7.BreakIterator.isBoundary
implementation that follows the existing spec is no longer compliant with the API spec in JDK 7.BreakIterator
implementation that is pluggable using the Locale Sensitive Services SPI (aka Pluggable Local SPI) needs to be updated to follow the spec change in order to be pluggable in JDK 7.BreakIterator
impementations need to be pluggable in both JDK 6 and JDK 7+, the implementations need to change the runtime behavior to follow the different specs.WToolkit
on Windows and XToolkit
on Linux/Solaris. The MToolkit
implementation on Linux/Solaris is no longer supported.
Toolkit
methods now throw HeadlessException
Toolkit.isFrameStateSupported(int)
, and Toolkit.loadSystemColors(int[])
, should throw a HeadlessException
when used in a headless environment. Prior to this release, this was not happening. Several methods in the Toolkit
class have been fixed to throw a HeadlessException
when invoked in a headless environment.