Skip Headers
SigTest User's Guide
Version 3.0
E19036-02
  Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
 
Next
Next
 

C API Migration Compatibility Rules (Signature Test)

This appendix describes the rules used by the Signature Test tool API migration feature.

C.1 The Compatibility Rules

The following sections and tables describe the rules and show whether they break only source compatibility or both source and binary compatibility. Comments and clarifications follow the table for rules that have an asterisk after their number.


Note:

A class is called subclassable if it has subclasses outside its package. In other words, this class is not final and has public constructor


C.1.1 General Rules

The rules from this group are triggered if the more specific rules from the other groups below are not triggered. For example, adding an interface method defined in rule 2.1, adding constructor in the rule 5.5. In such cases more general rule 1.1 is ignored.

Table C-1 API Migration Compatibility Rules - General

Rule # Description Breaks Severity

1.1 *

API (public or protected) type (class, interface, enum, annotation type) or member (method, field) added

Source

Warning

1.2

API (public or protected) type (class, interface, enum, annotation type) or member (method, field) removed

Both

Severe

1.3

Narrowing type or member visibility - from public to non-public, from protected to package or private

Both

Severe

1.4 *

Generification of the public API type

None



C.1.2 Interfaces and Annotation Types

The rules in this group apply to interfaces and annotation types.

Table C-2 API Migration Compatibility Rules - Interfaces and Annotation Types

Rule # Description Breaks Severity

2.1

Add abstract methods

Both

Severe

2.2

Add fields

Both

Severe

2.3 *

Expand the set of superinterfaces (direct or indirect) if the added interface has a field (constant)

Source

Warning

2.4

Contract superinterface set (direct or inherited)

Both

Severe

2.5 *

Add member without default value to annotation type

Source

Severe

2.6 *

Add member with default value to annotation type

None


2.7

Remove member from annotation type

Both

Severe

2.8

Remove default value from member of annotation type

Both

Severe


C.1.3 Interfaces and Class Methods

The rules in this group apply to interfaces and class methods.


Note:

Some rules in this group apply only for class methods.


Table C-3 API Migration Compatibility Rules - Interfaces and Class Methods

Rule # Description Breaks Severity

3.1

Change signature and/or return type

Both

Severe

3.2

Change last parameter from array type T[] to variable array T...

None


3.3

Change last parameter from array T... to array type T[]

Source

Severe

3.4

Change normalized throw list

Source

Severe

3.5

Decrease access from public to protected

Both

Severe

3.6 *

Increase access from protected to public if the class is subclassable

Source

Warning

3.7

Change method from abstract to non-abstract

None


3.8

Change method from non-abstract to abstract (if the class can be subclassed)

Both

Severe

3.9

Change method from final to non-final

None


3.10

Change method from non-final to final

Both

Severe

3.11

Change method from static to non-static

Both

Severe

3.12

Change method from non-static to static

Both

Severe

3.13

Change method from native to non-native

None


3.14

Change method from non-native to native

None


3.15

Change method from synchronized to non-synchronized

None


3.16

Change method from non-synchronized to synchronized

None



C.1.4 Interfaces and Class Fields

The rules in this group apply to interfaces and class methods.


Note:

Some rules from this group apply only for class fields


Table C-4 API Migration Compatibility Rules - Interfaces and Class Fields

Rule # Description Breaks Severity

4.1

Change type

Both

Severe

4.2

Change/Remove constant value

Both

Warning

4.3

Decrease access

Both

Severe

4.4

Increase access

None


4.5

Change from final to non-final

None


4.6

Change from non-final to final

Both

Severe

4.7

Change from static to non-static

Bone

Severe

4.8

Change from non-static to static

Both

Severe


C.1.5 Classes

The rules in this group apply to classes.

Table C-5 API Migration Compatibility Rules - General

Rule # Description Breaks Severity

5.1 *

Add non-abstract and non-static methods

Both

Warning

5.2

Add abstract methods (if the class can be subclassed)

Both

Severe

5.3

Add static methods (if the class can be subclassed)

Both

Warning

5.4

Remove constructors

Both

Severe

5.5

Add first constructor with arguments or throws clause

Both

Severe

5.6

Add fields

Both

Severe

5.7

Expand implemented interface set (direct or indirect)



5.7.1

The added interface adds abstract methods

Both

Severe

5.7.2

The new interface adds fields or inner classes

Source

Severe

5.7.3

If 5.7.1 and 5.7.3 are not true

None


5.8

Contract implemented interface set (direct or indirect)

Both

Severe

5.9

Expand superclass set (direct or indirect)



5.9.1

Add superclass adds abstract method (see rules 5.1 - 5.3)



5.9.2

Add superclass adds field (see rule 5.6)



5.9.3

Other cases



5.10

Contract superclass set (direct or indirect)

Both

Severe

5.11

Change abstract to non-abstract

None


5.12

Change non-abstract to abstract (if the class can be subclassed)

Both

Severe

5.13

Change final to non-final

None


5.14

Change non-final to final

Both

Severe


C.2 Comments and Clarifications

The following sections contain comments and clarifications that make the rules more clear.

C.2.1 Rule 1.1

Adding a class can theoretically break source code compatibility because new classes can be incorrectly resolved in an existing client's code with type-import-on-demand declarations (also know as wildcard imports). This can happen if the code uses another type with the same simple name. For example:

//client's code

import com.acme.*;
import com.client.*;

   .....

   Policy p = new Policy();   // this is com.client.Policy

   .....

In this case, after adding class com.acme.Policy, the compiler raises the error

reference to Policy is ambiguous, both class com.acme.Policy in com.acme and class com.client.Policy in com.client match.

This rule is considered a warning because it will probably not affect binary compatibility and adhering to this rule makes API evolution very difficult.

C.2.2 Rule 1.4

Generics are a facility of generic programming that was added to the Java programming language as part of Java SE version 5.0. Generics allow a type or method to operate on objects of various types while providing compile-time type safety. Generification upgrades types using support to-be-specified-later types that are instantiated as needed for specific types that are provided as type parameters.

The Java programming language implements generics using erasure, which ensures that legacy and generic versions usually generate identical class files, except for some auxiliary information about types. Binary compatibility is not broken because it is possible to replace a legacy class file with a generic class file without changing or recompiling any client code.

To facilitate interfacing with non-generic legacy code, it is also possible to use the erasure of a parameterized type as a type. Such a type is called a raw type (Java Language Specification 3/4.8). Allowing the raw type also ensures backward compatibility for source code.

According to this, the following versions of the java.util.Iterator class are both binary and source code backward compatible:

  • Class java.util.Iterator as it is defined in Java SE version 1.4:

    public interface Iterator {
        boolean hasNext();
        Object next();
        void remove();
    }
    
  • Class java.util.Iterator as it is defined in Java SE version 5.0:

    public interface Iterator<E> {
        boolean hasNext();
        E next();
        void remove();
    }
    

C.2.3 Rule 2.3

Adding a superinterface with a constant field can shadow another entity with the same simple name. Consider the following code:

public interface Poet{
    boolean LITERATE = true;
}

public interface Playwright{
    boolean LITERATE = true;
}

public interface Shakespeare extends Poet {

}

Suppose that a new version of the Shakespeare interface implements interface Playwright as well as Poet as shown here:

public interface Shakespeare extends Poet, Playwright {

}

The following client code will not compile because the reference to LITERATE is ambiguous.

// client code 
public class ShakespeareImpl implements Shakespeare {
    void introduce() {
        System.out.println("Hi, my name is Shakespeare and I'm " + LITERATE ?
                "quite literate" : "rather illiterate" );}
}

C.2.4 Rules 2.5, 2.6

The example below shows how adding a member without a default value to an annotation type breaks source code compatibility.

// annotation type v1
@interface Agent{
   String name();
}

// client's code which uses this annotation type v1
@Agent(name="James Bond")  


// annotation type v2.1
@interface Agent{
   String name();
   String id(); // added member
}

// legacy code is not compilable due to 
// error - annotation Agent is missing id
@Agent(name="James Bond")


// annotation type v2.2
@interface Agent{
   String name();
   String id() default "007";  // added member with default value
}

// legacy code is compilable
@Agent(name="James Bond") 

C.2.5 Rule 3.6

Changing a method from protected to public can break source code compatibility if this method was overridden as protected. In this case the legacy code can not be recompiled because ”access narrowing” is prohibited in the Java programming language. This rule is only a warning because it does not affect binary compatibility, and the probability of its affecting source code compatibility is very low.

C.2.6 Rule 4.2

Changing or removing constant values can break source code compatibility. For example, consider the following client code example. An integer constant named NOTHING with a value of 0 is used:

switch (i) {
    case NOTHING:
        // some actions
    case -1:
        // some other actions
}

Assume that the value of the constant NOTHING is changed from 0 to -1. The client code will not compile because of the duplicate case label. This rule is only a warning because it does not affect binary compatibility, and the probability of its affecting source code compatibility is very low.

C.2.7 Rule 5.1

Adding a regular method to a subclassable class can break source code and binary compatibility because a subclass can have a method with the same signature but with weaker access privileges. For example consider the following code example:

class ClientClass extends APIClass {
    private void foo() {}
}

Assume that the class APIClass is changed, and the method

protected void foo() {}

is added. The code cannot be recompiled due of an error that generates the following error message:

foo() in ClientClass cannot override foo() in APIClass; attempting to assign weaker access privileges; was protected

Binary compatibility is broken as defined in JLS 3/3.14.12

C.2.8 Rule 5.3

Adding a static method to a subclassable class can break source code and binary compatibility, because a subclass can have a method with the same signature. For example consider the following code example:

class ClientClass extends APIClass {
    protected void foo() {}
}

Suppose that the class APIClass is changed and the method

  protected static void foo() {}

is added. The code can not be recompiled due to an error that generates the following error message:

foo() in ClientClass cannot override foo() in APIClass; overridden method is static

Binary compatibility is be broken as defined in JLS 3/3.14.12

C.2.9 Rule 5.7.2

As in the case of rule 2.3, adding a superinterface with a constant field can shadow another entity with the same simple name.