My favorites | Sign in
Google
                
Search
for
Updated Mar 26, 2009 by amitman...@google.com
GwtJavaApiCompatibilityChecker  
Design document for the Java Api Compatibility Checker

Introduction

GWT Java API compatibility checker is a tool to check two versions of GWT for API source compatibility. In particular, the tool can ensure that newer releases of GWT are able to compile applications that previous versions could compile. A user can also specify explicit API changes that must be "white-listed," i.e., ignored by the tool. While we focus on GWT, this tool works for any Java API.

Background

A key advantage of GWT is that client applications (developed using GWT) do not have to worry about supporting new browsers or newer versions of a previously supported browser. GWT handles such issues. For example, when IE8 will be released, client application developers will be able to easily support IE8 by simply compiling their applications against a newer version of GWT. In general, as GWT continues to improve both in the quality of the JavaScript code it generates and the number of platforms it supports, client application developers can tap into these improvements by simply compiling the Java versions of their applications against the latest version of GWT. For client application developers to be able to successfully tap into these improvements, new GWT releases must successfully compile applications that previous versions could compile. We call this property API source compatibility.

As GWT's popularity increases, the challenge of maintaining GWT's API source compatibility is going to increase due to two factors. First, the GWT code is likely to become more complex over time as the number of features and platforms it supports increases. Second, the number of contributors to GWT is likely to increase as well. With increasing number of contributors, the changes to the source code will increase in both magnitude and number. Therefore it is desirable to automate the task of checking API source compatibility.

Other evolving APIs, most notably the Java language API, also face a similar problem 1]. Almost all of these APIs aim for binary compatibility, as specified in the Java language specification 2]. With binary compatibility, the aim for a new API release is to ensure that the client applications can use the class files of the new release in place of the class files of the previous release. There is no recompilation involved. Several tools exist for checking API binary compatibility 3, 4]. To the best of our knowledge, no tool exists for checking API source compatibility.

Of course, there can be cases when breaking the API is necessary. To handle these cases, the tool should support "white-lists." Specifying a whitelist explicitly should force the developers to think twice before breaking an API. The whitelist would also help client applications in refactoring their code appropriately.

Goals

The tool reports API differences between two collection of classes, as per API source compatibility. It supports all Java 1.5 features except annotations. It accepts a whitelist -- a list of the API changes that it must ignore. The changes it reports are:

Essentially, the tool should report an API change if any possible client application that could be compiled by the reference version of the API can no longer be compiled using the current version.

Non-Goals

The tool currently does not check for binary compatibility though it could be easily extended to check for binary compatibility. Similarly, the tool does not handle java annotations. It could be easily extended to handle annotations.

Use Cases

This section describes the use cases that ApiCompatibilityChecker will support.

java ApiCompatibilityChecker configFile

The ApiCompatibilityChecker tool requires a config file as an argument. The config file must specify two repositories of 
java source files: '_old' and '_new', which are to be compared for API source compatibility.

An optional whitelist is present at the end of the config file. The format of the whitelist is same as the output of the 
tool without the whitelist.

Each repository is specified by the following four properties:
name           specifies how the api should be refered to in the output
dirRoot        optional argument that specifies the base directory of all other file/directory names
sourceFiles    a colon-separated list of files/directories that specify the roots of the the filesystem trees to be included.
excludeFiles   a colon-separated lists of files/directories that specify the roots of the filesystem trees to be excluded

Example api.conf file:
name_old         gwtEmulator
dirRoot_old      ./
sourceFiles_old  dev/core/super:user/super:user/src
excludeFiles_old user/super/com/google/gwt/junit

name_new         gwtEmulatorCopy
dirRoot_new      ../gwt-14/
sourceFiles_new  dev/core:user/super:user/src
excludeFiles_new user/super/com/google/gwt/junit
java ApiCompatibilityChecker configFile 

We plan to put the tool into the GWT build, so that any update to the GWT trunk is checked for API compatibility against a reference version of GWT. Additionally, the tool will be used to check whether the JRE library support that GWT offers is compatible with the real JRE libraries. Ensuring this compatibility will allow developers to develop utility software that can be deployed on both the server-side and the client-side.

Proposed Solution

We build on TypeOracle, a compilation framework provided by GWT. Checking API source compatibility involves the following major steps:

  1. Read the configuration file, and build TypeOracles for the two source trees.
  2. For each of the two source trees, identify the API packages, classes, methods, fields, and constructors. First the API packages are identified. Then the API classes within the packages are identified. Finally, the API members of each API class is identified. The API members include both the members defined in the class as well as those inherited by the class.
  3. Find the API differences. First the list of Api packages for the two sources is compared to obtain the list of intersecting API packages and the list of missing API packages. For each interesecting packages, the list of API classes in the package for the two sources is compared to obtain the list of intersecting API classes and the list of missing API classes. For each intersecting class, the list of API members (fields, methods, and constructors) in the class for the two sources is compared to obtain the list of intersecting API members and the list of missing API members. Each intersecting API member and class is also checked for changes in modifiers (for example, if the keyword 'final' or 'abstract' was added) and changes in return types or the exceptions thrown.
  4. Remove duplicates from the API differences. We define duplicate as an API change message that is produced both for a class and its ancestor. For example, if 'java.lang.Object' had a public variable 'typeName' removed, we do not want the message to appear for all API classes.
  5. Remove API differences that are white-listed.

Identifying API elements is one of the key steps of this process. Below we describe our algorithm for identifying the API elements for different element types.

Discussion

The ApiCompatibilityChecker tool uses TypeOracle to compute the API differences. TypeOracle in turn requires access to the java source code. Thus the tool can only work when Java source is available. An alternative to TypeOracle would be to use Java reflection which works on class files, and would not have required access to the source files. However, we chose TypeOracle over Java relfection because with TypeOracle, we could tap into the already existing GWT compiler infrastructure. We could not find an analogous tool (with compatible licenses) in case of Java Reflection. (Japize, a tool which uses Java reflection to check for binary compatibility, could have been suitable, but the tool was under a GPL license.) With Reflection, everything would have to be developed from scratch.

References

  1. http://wiki.eclipse.org/index.php/Evolving_Java-based_APIs
  2. http://java.sun.com/docs/books/jls/third_edition/html/binaryComp.html
  3. http://clirr.sourceforge.net/
  4. http://sab39.netreach.com/Software/Japitools/Usage/japize/59/

Comment by scottb@google.com, Mar 26, 2009

Hey, what if we used ASM to process the class files? :D

Comment by tobyr+legacy@google.com, Mar 26, 2009

That's an excellent idea. I wish someone had thought of it earlier. ;)

In case it's not obvious, the biggest benefit of this is that we could compatibility check code that does not build, or is difficult to build, with TypeOracle?.


Sign in to add a comment