A type, method, or field is tagged with the @Deprecated
annotation. This change is neither a binary nor source incompatible change.
Detection
super
keyword.super
keyword.For example, there is an API type api.A
that contains the method mA()
. There is also a client type client.C
that contains the method mC()
, which invokes mA()
. If api.A
is annotated with @Deprecated
then mA()
is also tagged as deprecated, and the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+method:///api/A/mA()|,
methodInvocation(),
annotationDeprecatedAdded(binaryCompatibility=true,sourceCompatibility=true)
)
The field or its parent class is less accessible. Some client entities are not able to access this field anymore. The following table provides the less access permitted situations in Java (cf. JLS 13.4.7). We report which of them might break client code, and which exceptions must be considered regarding fields use.
Source | Target | Detection |
---|---|---|
public |
protected |
All field accesses except if they are made from a subtype of the owning class. Exceptions related to the public to package-private change are also considered. |
public |
package-private |
All field accesses except if they are made from a type in a package with the same qualified name as the constructor owning type. |
public |
private |
All field accesses. |
protected |
package-private |
All field accesses except if they are made from a type in a package with the same qualified name as the constructor owning type. |
protected |
private |
All field accesses. |
package-private |
private |
All field accesses. |
Detection
T
accessing a field of the type S
, where: i) T
is not a subtype of S
; ii)T
is not located in a package with the same qualified name as the parent package of S
, and; iii) the field in S
or S
itself goes from public
to protected
.T
accessing a field of the type S
, where: i) T
is not located in a package with the same qualified name as the parent package of S
, and; ii) the field in S
or S
itself goes from public
to package-private
or from protected
to package-private
.T
accessing a field of the type S
, where the field in S
goes from public
to private
, or from protected
to private
, or from package-private
to private
.For example, there is a client type client.C
with a method definition m()
, and an API type api.A
with a public
field f
.
Assume m()
accesses f
, and client.C
is not a subtype of api.A
.
If the visibility of m()
is changed to protected
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+field:///api/A/f|,
fieldAccess(),
fieldLessAccessible(binaryCompatibility=false,sourceCompatibility=false)
)
The field is more accessible than its previous version. Client types hiding such fields will break if the visibility of their own declaration is lower than the API definition (cf. JLS 13.4.8).
Detection
T
hiding a field of the type S
, where the new field declaration in T
is less accessible than the corresponding definition in S
.For example, there is an API type api.A
with a package-protected
field f
.
The latter is hidden in client type client.C
with a protected
visibility.
If the visibility of f
is changed to public
in api.A
, then the following detection is reported:
detection(
|java+field:///client/C/f|,
|java+field:///api/A/f|,
declaration(),
fieldMoreAccessible(binaryCompatibility=false,sourceCompatibility=true)
)
A field goes from static
to non-static
becoming an instance field.
The field cannot be accessed through its class, instead, it should be accessed through an object of the corresponding type.
Detection
static
.static
field with the same name of the target field (cf. JLS 13.4.8).For example, there is a client type client.C
with a method definition m()
, and an API type api.A
with a class field f
. Assume m()
accesses f
statically (i.e. A.f
). If f
is changed to non-static
in api.A
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+field:///api/A/f|,
fieldAccess(),
fieldNoLongerStatic(binaryCompatibility=false,sourceCompatibility=false)
)
A field goes from non-final
to final
, thus the field value cannot be modified.
Client code breaks if there is an attempt to assign a new value to the field.
Detection
final
.super
keyword a supertype field that is now final
and assigning it a new value.super
keyword a supertype field that is now final
and assigning it a new value.For example, there is a client type client.C
with a method definition m()
, and an API type api.A
with a field f
. Assume m()
accesses f
and assigns a new value to f
. If f
is declared as final
in api.A
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+field:///api/A/f|,
fieldAccess(),
fieldNowFinal(binaryCompatibility=false,sourceCompatibility=false)
)
A field goes from non-static
to static
.
This results in an IncompatibleClassChangeError
at linking time.
The problem rises given that the JVM uses two different instructions to access fields, getfield
and getstatic
.
The former is used to access objects fields and the latter to access static fields.
Client code must be recompiled to get rid of the issue (cf. JLS 13.4.10).
Detection
static
.static
through the super
keyword.static
without the super
keyword.For example, there is a client type client.C
with a method definition m()
, and an API type api.A
with a field f
. Assume m()
accesses f
. If f
is declared as static
in api.A
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+field:///api/A/f|,
fieldAccess(),
fieldNowFinal(binaryCompatibility=false,sourceCompatibility=false)
)
A field is removed from its parent class. Client projects are not able to access it anymore.
Detection
super
keyword.super
keyword.For example, there is a client type client.C
with a method definition m()
, and an API type api.A
with a field f
. Assume m()
accesses f
. If f
is removed from api.A
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+field:///api/A/f|,
fieldAccess(),
fieldRemoved(binaryCompatibility=false,sourceCompatibility=false)
)
A field is removed from a supertype class. Subtypes are not able to access it anymore.
Detection
super
keyword.super
keyword.For example, there is an API type api.A
that extends from the API type api.SuperA
. The latter declares a field f
. There is also a client type client.C
that extends api.A
. Type client.C
has a method definition m()
. Assume m()
accesses f
. If f
is removed from api.SuperA
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+field:///api/SuperA/f|,
fieldAccess(),
fieldRemovedInSuperclass(binaryCompatibility=false,sourceCompatibility=false)
)
The type of the field has changed. Check conversion cases in variable assignment, invocation, String, casting, and numeric contexts (cf. JLS 5.1). Check the following table:
Conversion type | Description | Breakage |
---|---|---|
Identity | Type T to type T |
Never |
Widening primitive | Smaller primitive type to wider primitive type | Never |
Narrowing primitive | Wider primitive type to smaller primitive type | Sometimes |
Widening reference | Subtype T to supertype ST |
Never |
Narrowing reference | Supertype ST to subtype T |
Sometimes |
Boxing | Primitive type P to wrapper reference type R |
Never |
Unboxing | Wrapper reference type R to primitive type P |
Sometimes |
Unchecked | Interface type G to parameterized type G<T1,..,Tn> |
Sometimes |
Detection
super
keyword.super
keyword.For example, there is a client type client.C
with a method definition m()
, and an API type api.A
with a field f
of type T
. Assume m()
accesses f
. If the type of f
is changed to type R
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+field:///api/A/f|,
fieldAccess(),
fieldTypeChanged(binaryCompatibility=false,sourceCompatibility=false)
)
The constructor or its parent class is less accessible. Client entities cannot create objects with this method. The following table provides the less access permitted situations in Java (cf. JLS 13.4.7). We report which of them might break client code, and which exceptions must be considered regarding constructors’ use.
Source | Target | Detection |
---|---|---|
public |
protected |
All invocations except if the invocation is made from a subtype of the owning class. Exceptions related to the public to package-private change are also considered |
public |
package-private |
All invocations except if the invocation is made from a type in a package with the same qualified name as the constructor owning type |
public |
private |
All invocations of the method |
protected |
package-private |
All invocations except if the invocation is made from a type in a package with the same qualified name as the constructor owning type |
protected |
private |
All invocations of the method |
package-private |
private |
All invocations of the method |
Detection
T
invoking a constructor of type S
, where: i) T
is not a subtype of S
; ii)T
is not located in a package with the same qualified name as the parent package of S
, and; iii) the constructor of S
or S
itself goes from public
to protected
.T
invoking a constructor of type S
, where: i) T
is not located in a package with the same qualified name as the parent package of S
, and; ii) the constructor of S
or S
itself goes from public
to package-private
or from protected
to package-private
.T
invoking a constructor of type S
, where the constructor of S
goes from public
to private
, or from protected
to private
, or from package-private
to private
.For example, there is a client type client.C
with a method definition m()
, and an API type api.A
with a public
constructor A()
. Assume m()
invokes A()
to create an object of type api.A
. If the access modifier of A()
is changed to private
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+constructor:///api/A/A()|,
methodInvocation(),
constructorLessAccessible(binaryCompatibility=false,sourceCompatibility=false)
)
If the constructor or the parent class is removed, this issue is reported. Client projects are not able to create objects with the corresponding method.
Detection
super
keyword.For example, there is a client type client.C
with a method definition m()
, and an API type api.A
with a constructor A(int)
. Assume m()
invokes A(int)
to create an object of type api.A
. If A(int)
is removed from api.A
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+constructor:///api/A/A(int)|,
methodInvocation(),
constructorRemoved(binaryCompatibility=false,sourceCompatibility=false)
)
An abstract method is added to a superclass and no implementation is provided in (maybe part of) the API hierarchy. This change is reported only if subtypes are abstract. Client types affected by this issue extend one of the subtypes of the superclass where the abstract method was added. We do not provide detections linked to this type of change. Instead, we detect this and more general cases through the Method Abstract Added to Class change.
A new abstract method is added to a class. All non-abstract client classes extending the modified class or an abstract subtype will break, given that the definition of the target method is missing. This will result in a compilation error (i.e. source incompatible). However, at the binary level, no breakage is detected given that there cannot be calls to the new method when using the old version of the API (cf. JLS 13.5.3.). In addition, the JVM does not check if there are missing method implementations at linking time.
Detection
For example, there is a client type client.C
that extends the API abstract class api.A
. Assume api.A
declares a new abstract method m()
in its body, then the following detection is reported:
detection(
|java+class:///client/C|,
|java+method:///api/A/m()|,
extendss(),
methodAddedToClass(binaryCompatibility=true,sourceCompatibility=false)
)
An abstract method in an interface is now declared as a default method.
As stated in the JLS, this change results in an IncompatibleClassChangeError
linkage error only in the following scenario.
Type T
implements interfaces I
and J
.
I
is not a subinterface of J
and viceversa.
J
has a default method m()
.
Now, we add a new default method in I
with the same signature and return type of m()
.
Suppose there is an invocation of m()
in T
that does not follow the form J.super.m()
.
With this change T
will link without error but once the invocation to m()
is triggered an error is thrown.
In any case, this change might result in unpredictable behaviour or a compilation error (c.f. JLS 13.5.6).
Detection
For example, there is a client type client.C
, and two API interfaces api.I
and otherapi.J
.
The type client.C
implements both api.I
and otherapi.J
.
Suppose api.I
and otherapi.J
declare an abstract method m()
(each one of them has its own definition).
If the API evolves and api.I
changes m()
from an abstract to a default method, and client.C
has no method definition of m()
, then the following detection is reported:
detection(
|java+class:///client/C|,
|java+method:///api/I/m()|,
implements(),
methodAbstractNowDefault(binaryCompatibility=false,sourceCompatibility=false)
)
A new method is added to an interface. All client classes implementing the interface will break given that the implementation of the target method is missing. This will result in a compilation error (i.e. source incompatible). However, at the binary level, no breakage is detected given that there cannot be calls to the new method when using the old version of the API (cf. JLS 13.5.3.). In addition, the JVM does not check if there are missing method implementations at linking time.
Detection
For example, there is a client type client.C
that implements the API interface api.IA
. Assume api.IA
declares a new method m()
in its body, then the following detection is reported:
detection(
|java+class:///client/C|,
|java+method:///api/IA/m()|,
implements(),
methodAddedToInterface(binaryCompatibility=true,sourceCompatibility=false)
)
The method or its parent class is less accessible. Some client entities are not able to invoke this method anymore. The following table provides the less access permitted situations in Java (cf. JLS 13.4.7). We report which of them might break client code, and which exceptions must be considered regarding methods use.
Source | Target | Detection |
---|---|---|
public |
protected |
All method invocations and overrides except if they are made from a subtype of the owning class. Exceptions related to the public to package-private change are also considered. |
public |
package-private |
All method invocations and overrides except if they are made from a type in a package with the same qualified name as the constructor owning type. |
public |
private |
All method invocations and overrides. |
protected |
package-private |
All method invocations and overrides except if they are made from a type in a package with the same qualified name as the constructor owning type. |
protected |
private |
All method invocations and overrides. |
package-private |
private |
All method invocations and overrides. |
Detection
T
invoking or overriding a method of the type S
, where: i) T
is not a subtype of S
; ii)T
is not located in a package with the same qualified name as the parent package of S
, and; iii) the method in S
or S
itself goes from public
to protected
.T
invoking or overriding a method of the type S
, where: i) T
is not located in a package with the same qualified name as the parent package of S
, and; ii) the method in S
or S
itself goes from public
to package-private
or from protected
to package-private
.T
invoking or overriding a method of the type S
, where the method in S
goes from public
to private
, or from protected
to private
, or from package-private
to private
.For example, there is a client type client.C
with a method definition mC()
, and an API type api.A
with a public
method mA()
.
Assume mC()
invokes mA()
.
If the visibility of mA()
is changed to package-private
, then the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+method:///api/A/mA()|,
methodInvocation(),
methodLessAccessible(binaryCompatibility=false,sourceCompatibility=false)
)
The method is more accessible than its previous version. Client types overriding such methods will break if the visibility of their own declaration is lower than the API definition.
Detection
T
overriding a method of the type S
, where the new method declaration in T
is less accessible than the corresponding definition in S
.For example, there is an API type api.A
with a protected
method m()
.
The latter is overridden in client type client.C
with a protected
visibility.
If the visibility of m()
is changed to public
in api.A
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+method:///api/A/m()|,
methodOverride(),
methodMoreAccessible(binaryCompatibility=false,sourceCompatibility=false)
)
A new default method is declared in an interface.
As stated in the JLS, this change results in an IncompatibleClassChangeError
linkage error only in the following scenario.
Type T
implements interfaces I
and J
.
I
is not a subinterface of J
and viceversa.
J
has a default method m()
.
Now, we add a new default method in I
with the same signature and return type of m()
.
Suppose there is an invocation of m()
in T
that does not follow the form J.super.m()
.
With this change T
will link without error but once the invocation to m()
is triggered an error is thrown.
In any case, this change might result in unpredictable behaviour or a compilation error (c.f. JLS 13.5.6).
Detection
For example, there is a client type client.C
, and two API interfaces api.I
and otherapi.J
.
The type client.C
implements both api.I
and otherapi.J
.
Suppose otherapi.J
defines method m()
as a default method.
The API evolves and api.I
has a new default method m()
with the same signature as the one provided in otherapi.J
.
If client.C
has no definition of a method m()
that overrides the previous implementation, then the following detection is reported:
detection(
|java+class:///client/C|,
|java+method:///api/I/m()|,
implements(),
methodNewDefault(binaryCompatibility=false,sourceCompatibility=false)
)
A field goes from static
to non-static
becoming an instance field. The field cannot be accessed through its class, instead, it should be accessed through an object of the corresponding type.
Detection
static
.static
method with the same name of the target method (cf. JLS 13.4.12).For example, there is a client type client.C
with a method definition mC()
, and an API type api.A
with a static method mA()
. Assume mC()
invokes mA()
in a static manner (i.e. A.mA()
). If the static
modifier is removed from mA()
, then the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+method:///api/A/mA()|,
fieldAccess(),
methodNoLongerStatic(binaryCompatibility=false,sourceCompatibility=false)
)
A method goes from non-abstract
to abstract
. Non-abstract client types must provide an implementation. Method invocations pointing to the target method will break.
Detection
abstract
in the direct parent type and no implementation is provided.abstract
in a transitive parent type and no implementation is provided.For example, there is a client type client.C
with a method definition mC()
, and an API type api.A
with a method mA()
. Assume mC()
invokes mA()
. If mA()
is declared as abstract
in api.A
, then the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+method:///api/A/mA()|,
methodInvocation(),
methodNowAbstract(binaryCompatibility=false,sourceCompatibility=false)
)
A method goes from non-final
to final
, thus the method cannot be overridden. Client code breaks if there is an attempt to override the method.
Detection
final
in the direct parent type.final
in a transitive parent type.For example, there is a client type client.C
with a method definition mC()
, and an API type api.A
with a method mA()
. Assume mC()
overrides mA()
. If mA()
is declared as final
in api.A
, then the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+method:///api/A/mA()|,
methodOverride(),
methodNowFinal(binaryCompatibility=false,sourceCompatibility=false)
)
A method goes from non-static
to static
. This results in a linkage error, mainly because static methods must be invoked with the JVM instruction invokestatic
. Client code must be recompiled to get rid of the issue (cf. JLS 13.4.19).
Detection
static
.static
through the super
keyword.static
without the super
keyword.static
in the direct parent type.static
in a transitive parent type.For example, there is a client type client.C
with a method definition mC()
, and an API type api.A
with a method mA()
. Assume mC()
invokes mA()
. If mA()
is declared as static
in api.A
, then the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+method:///api/A/mA()|,
methodInvocation(),
methodNowStatic(binaryCompatibility=false,sourceCompatibility=false)
)
A method adds a new exception to the throws
clause in its declaration.
This change is binary compatible.
However, it triggers a set of compilation errors given that client entities invoking the method need to handle the new exception.
Detection
try-catch
block that catches the new exception.For example, there is a client type client.C
with a method mC()
.
There is also an API type api.A
with a method mA()
that does not throw any exception.
mC()
invokes mA()
without using a try-catch
block.
If the declaration of mA()
is changed so it now throws a new checked exception,
then the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+class:///api/A/mA()|,
methodInvocation(),
methodNowThrowsCheckedException(binaryCompatibility=true,sourceCompatibility=false)
)
A method is removed from its parent class. Client projects are not able to invoke it anymore.
Detection
super
keyword.super
keyword.For example, there is a client type client.C
with a method definition mC()
, and an API type api.A
with a method mA()
.
Assume mC()
invokes mA()
.
If mA()
is removed from api.A
, then the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+method:///api/A/mA()|,
methodInvocation(),
constructorRemoved(binaryCompatibility=false,sourceCompatibility=false)
)
A method is removed from a supertype class. Subtypes are not able to invoke it anymore.
Detection
super
keyword.super
keyword.For example, there is an API type api.A
that extends from the API type api.SuperA
. The latter defines a method mSuper()
. There is also a client type client.C
that extends api.A
. Type client.C
has a method definition m()
. Assume m()
invokes mSuper()
. If mSUper()
is removed from api.SuperA
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+method:///api/SuperA/mSuper()|,
methodInvocation(),
methodRemovedInSuperclass(binaryCompatibility=false,sourceCompatibility=false)
)
The return type of the method has changed. Check conversion cases in assignment, invocation, String, casting, and numeric contexts (cf. Java Language Specification Chapter 5.1). Check the following table:
Conversion type | Description | Breakage |
---|---|---|
Identity | Type T to type T |
Never |
Widening primitive | Smaller primitive type to wider primitive type | Never |
Narrowing primitive | Wider primitive type to smaller primitive type | Sometimes |
Widening reference | Subtype T to supertype ST |
Never |
Narrowing reference | Supertype ST to subtype T |
Sometimes |
Boxing | Primitive type P to wrapper reference type R |
Never |
Unboxing | Wrapper reference type R to primitive type P |
Sometimes |
Unchecked | Interface type G to parameterized type G<T1,..,Tn> |
Sometimes |
Detection
super
keyword.super
keyword.For example, there is a client type client.C
with a method definition mC()
, and an API type api.A
with a method mA()
with return type T
. Assume mC()
invokes mA()
. If the return type of mA()
is changed to type R
, then the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+method:///api/A/mA()|,
methodInvocation(),
methodReturnTypeChanged(binaryCompatibility=false,sourceCompatibility=false)
)
The type is less accessible. Some client entities are not able to depend on, be annotated with, implement, or inherit from this type anymore (cf. JLS 13.4.3). The following table provides the less access permitted situations in Java (cf. JLS 13.4.7). We report which of them might break client code, and which exceptions must be considered regarding methods use.
Source | Target | Detection |
---|---|---|
public |
protected |
(Only applicable to inner types.) All entities depending on, or all types implementing or extending the target type except if they are subtypes of the supertype of the target type. Exceptions related to the public to package-private change are also considered. |
public |
package-private |
All entities depending on, or all types implementing or extending the target type except if they are placed in a package with the same qualified name as the target type. |
public |
private |
All entities depending on, or all types implementing or extending the target type. |
protected |
package-private |
All entities depending on, or all types implementing or extending the target type except if they are placed in a package with the same qualified name as the target type. |
protected |
private |
All entities depending on, or all types implementing or extending the target type. |
package-private |
private |
All entities depending on, or all types implementing or extending the target type. |
Detection
T
depending on or being annotated with type S
, where: i) T
is not a subtype of S
; ii) T
is not located in a package with the same qualified name as the parent package of S
, and; iii) S
goes from public
to protected
.T
implementing or extending type S
, where: i) T
is not a subtype of S
; ii) T
is not located in a package with the same qualified name as the parent package of S
, and; iii) S
goes from public
to protected
.T
depending on or being annotated with type S
, where: i) T
is not located in a package with the same qualified name as the parent package of S
, and; ii) S
goes from public
to package-private
.T
implementing or extending type S
, where: i) T
is not located in a package with the same qualified name as the parent package of S
, and; ii) S
goes from public
to package-private
.T
depending on or being annotated with type S
, where: i) T
is not located in a package with the same qualified name as the parent package of S
, and; ii) S
goes from protected
to package-private
.T
implementing or extending type S
, where: i) T
is not located in a package with the same qualified name as the parent package of S
, and; ii) S
goes from protected
to package-private
.T
depending on or being annotated with type S
, where S
goes from any visibility to private
.T
implementing or extending type S
, where S
goes from any visibility to private
.For example, there is a client type client.C
with a method definition mC()
.
There is also a public API type api.A
with a public method mA()
.
client.C
extends api.A
.
Method mC()
invokes mA()
through the super
keyword.
If the visibility of api.A
is changed from public
to package-private
, then the following detection is reported:
detection(
|java+method:///client/C/mC()|,
|java+class:///api/A|,
typeDependency(),
classLessAccessible(binaryCompatibility=false,sourceCompatibility=false)
)
The visibility of a class is reduced from public
or protected
to any other access modifier.
If a client member depends on the modified type and the change forbids the client member access to the type, then an IllegalAccessError
is reported at link time (cf. JLS 13.4.3).
A compilation error is also obtained.
Detection
For example, there is a client type client.C
with a method definition m(api.A)
, and a public API type api.A
.
If the visibility of api.A
is changed from public
to package-private
, then the following detection is reported:
detection(
|java+parameter:///client/C/m(api.A)/param0|,
|java+class:///api/A|,
typeDependency(),
classNoLongerPublic(binaryCompatibility=false,sourceCompatibility=false)
)
A class goes from non-abstract
to abstract
. It is not possible to create new objects from the given type.
Detection
abstract
type.abstract
supertype through the super
keyword (?).abstract
supertype without the super
keyword (?).For example, there is a client type client.C
with a method definition m()
, and an API type api.A
. Assume m()
creates an object of type api.A
by invoking its constructor A()
. If api.A
is declared as abstract
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+constructor:///api/A/A()|,
methodInvocation(),
classNowAbstract(binaryCompatibility=false,sourceCompatibility=false)
)
A class extends from java.lang.Exception
.
This change is binary compatible.
However, it triggers a set of compilation errors given that methods depending on the modified type need to add it in the throws declaration.
Detection
For example, api.E
is an unchecked exception inheriting from java.lang.RuntimeException
.
There is a client type client.C
that has a method definition m()
.
At some point, method m()
creates and throws api.E
without adding the exception to the method declaration.
If api.E
inherits now from java.lang.Exception
, then the following detection is reported:
detection(
|java+method:///client/C/m()|,
|java+class:///api/E|,
methodInvocation(),
classNowCheckedException(binaryCompatibility=true,sourceCompatibility=false)
)
A class goes from non-final
to final
, thus the class cannot be extended by other types anymore.
Detection
final
.final
.For example, there is a client type client.C
and an API type api.A
. If client.C
extends api.A
and api.A
is declared as final
, then the following detection is reported:
detection(
|java+class:///client/C|,
|java+class:///api/A|,
extends(),
classNowFinal(binaryCompatibility=false,sourceCompatibility=false)
)
API members depending on or annotated with the removed type are affected. Types extending or implementing the removed type cannot use it anymore.
Detection
For example, there is an API type api.A
and a client type client.C
. The latter extends api.A
. If api.A
is removed, client.C
cannot include this inheritance in the class declaration, then the following detection is reported:
detection(
|java+class:///client/C|,
|java+class:///api/A|,
extends(),
classRemoved(binaryCompatibility=false,sourceCompatibility=false)
)
The type of the class changes.
A class type could be class
, interface
, enum
, or annotation
.
The following table provides a set of cases where client code might break when changing the type of a class. Some of these cases are detected by other API change detections. We still mention them to have the overall picture of possible situations. We also report on our assumptions during the bytecode analysis.
Source | Target | Detection |
---|---|---|
class |
Any | Client classes cannot extend it. |
class |
interface |
The constructor of the class cannot be invoked (cf. Method Now Abstract or Method Removed) |
class |
enum |
The constructor of the class cannot be invoked (cf. Constructors Less Accessible) |
class |
annotation |
Client entities cannot depend on the type. |
interface |
Any | Client interfaces cannot extend it. Client classes cannot implement it. |
interface |
annotation |
Client entities cannot depend on the type. |
enum |
Any | Static access of enum fields might be affected (cf. Field No Longer Static) |
enum |
annotation |
Client entities cannot depend on the type. |
annotation |
Any | Client entities cannot be tagged with the annotation. |
Assumptions:
class
type does not appear in the implements
relation as implemented type.interface
type can also be extended by other interfaces.enum
types, we expect no occurrence in the extends
and implements
relation (an enum
can only extend the java.lang.Enum
class).class
type is changed to an interface
, expect detections related to Class Now Abstract and Method Now Abstract changes.Detection
class
to any other class type.class
to annotation
.interface
to any other class type.interface
to any other class type.interface
to annotation
.enum
to annotation
.annotation
to any other class type.For example, there is an API interface api.IA
and a client type client.C
.
The latter implements api.IA
.
If the type of api.IA
is changed from interface
to class
, client.C
cannot implement the type anymore.
Then, the following detection is reported:
detection(
|java+class:///client/C|,
|java+interface:///api/IA|,
implements(),
classTypeChanged(binaryCompatibility=false,sourceCompatibility=false)
)
A type removes an interface from its set of interfaces. Some castings might result in a linkage (or runtime) error. Subtypes won’t be able to access interface fields and default methods anymore. Moreover, method overriding of the removed interface methods also raise a compilation error (cf. JLS 13.4.4).
Detection
For example, there is an abstract API class api.A
, an API interface api.IA
, and a client type client.C
.
The class api.A
implements api.IA
and client.C
extends api.A
.
Method m()
in client.C
overrides the corresponding method declared in api.IA
.
If api.IA
is removed from the set of innterfaces of api.A
then m()
cannot override the corresponding method of the interface anymore.
The following detection is then reported:
detection(
|java+class:///client/C|,
|java+class:///api/A|,
extends(),
interfaceAdded(binaryCompatibility=true,sourceCompatibility=false)
)
A type adds an interface to its set of superinterfaces. Subtypes of an abstract affected type are obliged to override the interface methods (if any) (cf. JLS 13.4.4).
Detection
For example, there is an abstract API class api.A
, an API interface api.IA
, and a client type client.C
.
The class client.C
extends api.A
and api.IA
declares method m()
.
If api.IA
is added to the set of superinterfaces of api.A
then client.C
is forced to override m()
.
The following detection is then reported:
detection(
|java+class:///client/C|,
|java+interface:///api/IA|,
implements(),
interfaceAdded(binaryCompatibility=true,sourceCompatibility=false)
)
A type removes its original superclass. Castings might result in a compilation error. Subtypes won’t be able to access superclass fields and methods anymore. Method overriding of the removed superclass methods also raise a compilation error (cf. JLS 13.4.4).
Detection
For example, there is an abstract API class api.A
, an API superclass api.SA
, and a client type client.C
.
The class api.A
extends api.SA
and client.C
extends api.A
.
Method m()
in client.C
overrides the corresponding method declared in api.SA
.
If api.IA
is not the superclass of api.A
anymore, then m()
cannot override the corresponding method of the superclass.
The following detection is then reported:
detection(
|java+class:///client/C|,
|java+class:///api/A|,
extends(),
superclassAdded(binaryCompatibility=true,sourceCompatibility=false)
)
A type adds a superclass. Subtypes of an abstract affected type are obliged to override the type methods (if any) (cf. JLS 13.4.4).
Detection
For example, there is an abstract API class api.A
, an API superclass api.SA
, and a client type client.C
.
The class client.C
extends api.A
and api.SA
declares the abstract method m()
.
If api.SA
is now the superclass of api.A
then client.C
is forced to override m()
.
The following detection is then reported:
detection(
|java+class:///client/C|,
|java+class:///api/SA|,
extends(),
superclassAdded(binaryCompatibility=false,sourceCompatibility=false)
)
This repository—and all its content—is licensed under the MIT License. © 2018-2021 Maracas