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:
getMethodsgetDeclaredMethodsgetDeclaredConstructorsclass 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.