Type Annotations (JSR 308) Compiler README

Version 2.1.10 (3 Apr 2017)

For the latest version, see the Type Annotations (JSR 308) webpage.

Contents:

Introduction

(If you are impatient, you can skip to the installation instructions.)

The Type Annotations compiler is a version of the OpenJDK Java 8 compiler that supports some extra features for type annotations. The OpenJDK Java 8 compiler will support the Type Annotations (JSR 308) syntax, which permits annotations to appear on types. The extra features in the Type Annotations compiler make it possible for you write (and type-check) type annotations, while still permitting your code to be compiled with a Java 4/5/6/7 compiler.

You may use the Type Annotations compiler as a replacement for the OpenJDK javac compiler or any other Java compiler.

Pluggable type-checking is made possible by the Type Annotations syntax. Pluggable type-checking is made easy by the Checker Framework. It includes several example type qualifiers that you can start using right away, and it enables you to create your own new compiler plug-ins that check user-defined type qualifiers. If you want to use the Checker Framework, we recommend that you install it rather than following the instructions on this webpage.

The “Installing the Type Annotations compiler” section below contains instructions for installing, running, and testing the compiler.

IntelliJ IDEA (Maia release) supports the Type Annotations (JSR 308) syntax. Other IDEs (such as Eclipse and NetBeans) are being updated to support the Type Annotations syntax. For Eclipse, write an Ant buildfile that compiles your project using the Type Annotations compiler (and maybe does pluggable type-checking too), then build by running Ant. Problem markers will show up in the Eclipse IDE as normal. (You will lose a few Eclipse features, such as error checking as you type, until Eclipse's internal compiler is updated for to support type annotations.)

Installing the Type Annotations compiler

The easiest way to install the Type Annotations compiler, which is sufficient for most users, is to install the Checker Framework. The Checker Framework contains the Type Annotations compiler, so if you install the Checker Framework (from its distribution, or building it from source), you do not need the instructions on this webpage.

The remainder of this section gives instructions for installing the Type Annotations compiler from source.

Building from source is useful mainly for people who are developing compiler plug-ins or modifying the compiler itself. Also, if you use an Apple Macintosh (Mac OS X) computer, you must build the compiler from source.

Note that while these instructions install the Type Annotations compiler, you do not have to make it your default compiler. For example, you could use the Type Annotations compiler only for running pluggable type-checkers. Also, you can use javac's -target argument to generate bytecodes that are compatible with earlier JVMs, so that you can work seamlessly with colleagues who are using an earlier version of Java.

Installing from source

Requirements: These instructions assume that Ant (version 1.7 or later) and the JDK (version 6 or later) are installed. Furthermore, the JAVA_HOME environment variable should be set to the location of your JDK installation. Most likely it is already set for Ant to work.

  1. Install a new copy of the Oracle JDK. This new installation will be modified later (but no other copy of the JDK will be modified). You can put the new installation anywhere you want; a common place is in a new directory ~/jsr308. We will call that directory $JSR308.
    1. Download a JDK 7 binary snapshot or JDK 8 binary snapshot: self-extracting JDK file. Choose JDK, not JRE or DEBUG, and choose a binary, not a source distribution. The rest of these instructions assume JDK 8, but they work just as well with JDK 7.
    2. Follow the installation instructions — essentially, just run the .exe, .sh, or .bin file that you downloaded and follow the directions.
    3. Optionally set the default version of Java. (At any time, you can run either the default or the non-default version of Java.)
      • For Linux: After installing, your old version of Java remains the default. If you wish to make JDK Java 8 the default, then set your JAVA_HOME environment variable to the top-level directory of the JDK 8 installation /path/to/jdk1.8.0, and augment your PATH with /path/to/jdk1.8.0/bin. Example:
        export JSR308=$HOME/jsr308
        export JAVA_HOME=$JSR308/jdk1.8.0
        export PATH=$JAVA_HOME/bin:$PATH
        
        The shell uses the PATH variable to locate java, while Ant uses JAVA_HOME.
      • For Windows: After installing, the JDK Java 8 (at c:\Program Files\Java\jdk1.8.0\) becomes the default. If you wish to retain an older version of Java as the default, then do the following:
        1. Install Java 8
        2. Copy the jdk1.8.0 and jre1.8.0 directories from Program Files\Java\ to the desktop
        3. Uninstall Java 8
        4. Move the jdk/jre directories back to Program Files\Java\
        If you want to be able to run javac from Cygwin, then set environment variables as for Linux, above.
    4. Verify that your installation is correct: run javac -version, and the output should be javac 1.8.0-ea.
  2. Download the Type Annotations compiler, and unpack it to create a jsr308-langtools directory. Do not do this inside the JDK 8 installation (directory jdk1.8.0) that you downloaded in the preceding step. Example commands:
    mkdir ~/jsr308
    cd ~/jsr308
    wget https://checkerframework.org/jsr308-langtools.zip
    unzip jsr308-langtools.zip
    
  3. Compile the Type Annotations javac compiler and the javap tool, from directory jsr308-langtools/make:
    cd jsr308-langtools/make
    ant clean build-javac build-javap
    
    Add the jsr308-langtools/dist/bin directory to the front of your PATH environment variable.

    The effect of the above commands is that the javac command invokes the Type Annotations Java compiler and the javap command invokes the Type Annotations javap, but the Java 8 JDK is used for everything else.

  4. Run
    javac -version
    
    and confirm that the output contains the string jsr308, such as javac 1.8.0-jsr308-1.1.1.
    If the output does not contain jsr308 (e.g., it is javac 1.8.0-ea), but you are using the correct javac binary (in jsr308-langtools/dist/bin), then it is possible that tools.jar is on your classpath. You should either remove tools.jar from your classpath, or else put jsr308-langtools/dist/lib/javac.jar and/or jsr308-langtools/dist/lib/javap.jar on your classpath before tools.jar.

When updating to a newer version of the Type Annotations compiler, you only have to follow steps 2, 3, and 4. In other words, you only have to redo step 1 if you want a newer version of JDK.

Features of the Type Annotations compiler

Type Annotations (JSR 308) features

The new type annotations features (which appear in both OpenJDK and in the Type Annotations compiler) are:

Differences from the OpenJDK compiler

The Type Annotations distribution includes only the langtools portion of OpenJDK. The Type Annotations compiler makes no modifications in other parts of OpenJDK, and the remaining parts of OpenJDK are not necessary to build and use the Type Annotations tools.

This Type Annotations distribution differs from the langtools portion of Oracle's OpenJDK distribution in the following ways:

Binary builds (for Windows, Solaris, Linux, and Mac OS) of the JSR 308 Reference Implementation are available from Oracle at http://jdk8.java.net/type-annotations/. This is essentially the OpenJDK implementation under a binary evaluation-and-testing license.

Writing annotations in comments for forward compatibility

The UW version of the Type Annotations compiler supports writing annotations and code in comments, and implicitly importing packages. These are temporary features that make it easy to write code that contains type annotations but that also compiles when using earlier versions of Java. These features will not be supported by the Oracle OpenJDK compiler.

For additional information about these features, see the Checker Framework Manual.

Annotations in comments

The Type Annotations compiler allows annotations to be written in “/* */” (C-style) comments, for example:

  List</*@NonNull*/ String> strings;

There must be no whitespace at the beginning or end of the comment.

These mechanism allows developers to use type annotations while maintaining the ability to compile their code with an unmodified Java compiler, including compilers for earlier versions of the Java language (such as Java 4, Java 5, Java 6, or Java 7).

Code in comments

There is a more powerful mechanism that permits arbitrary code to be written in a comment that is formatted as “/*>>> */”, with the first three characters of the comment being greater-than signs. As with annotations in comments, the commented code is ignored by ordinary compilers but is treated like ordinary code by the UW Type Annotations compiler.

This mechanism is intended only to support writing import statements and the new receiver (“this”) syntax, as in

public boolean getResult(/*>>> @ReadOnly TestRun this*/) { ... }

for a method that does not modify its receiver.

It would be possible to abuse this mechanism to inject code only when using the Type Annotations compiler. Doing so is not a sanctioned use of the mechanism.

Type annotations in Java 6 or 7 classfiles

If you specify the -source 6 -target 6 or -source 7 -target 7 command-line options and the compiler reads type annotations from comments, then the compiler writes the type annotations to the generated classfile. They will be read by the compiler during subsequent compilations, which enables separate compilation.

However, these annotations will be ignored by an ordinary Java 8 compiler, which won't even look for type annotations in a classfile generated with -target 7 or earlier.

Determining a diff against the OpenJDK distribution

The Type Annotations distribution is a modification of the langtools portion of Oracle's OpenJDK javac distribution.

The following commands determine the differences between the Type Annotations compiler and the OpenJDK compiler.

  1. If you do not have a clean checkout of the Type Annotations compiler source, obtain one:
    hg clone https://bitbucket.org/typetools/jsr308-langtools/ jsr308-langtools
    If you already have one, then just pull all the changes, by running the following command in the directory containing the Type Annotations compiler source:
    hg pull; hg update
  2. Determine the identifier of the last changeset done by Oracle. Run "hg log | less" to find the last changeset with an author other than mahmood, mali, mernst, notnoop, wdietl, or wmdietl. The changeset identifier is in the format:
    450:143956db282e
  3. Use hg diff to generate the diff.
    hg diff -r450:tip

Contributing

We welcome bug fixes, new features, type-checking plug-ins, and other improvements. Any code contributed to javac or to the Type Annotations compiler is contributed to Oracle under Oracle's Contributor Agreement (SCA).

How to report bugs

To report a bug, use the issue tracking system.
Please see below for details that will help you submit an informative bug report to the right developers, that is most likely to be accepted and fixed.
Thank you for your bug report!

What bugs should you report?

If you have any problems with the compiler, please let us know. We welcome bug reports and suggestions, and we want to help. We will fix all reported bugs in the Type Annotations compiler. Examples of bugs include:

Whenever you get a message such as

  An exception has occurred in the compiler (1.8.0-jsr308-1.2.1). Please
  report this bug so we can fix it.  For instructions, see
  https://checkerframework.org/README-jsr308.html#reporting-bugs

then you should always report it. However, there are three different places you might need to report the bug. Please report it in the appropriate place, and it is more likely to be fixed.

To whom should you report the bug?

The Type Annotations compiler is built on Oracle's OpenJDK compiler, and annotation processors use the Type Annotations compiler. If you find a bug while using the Type Annotations compiler:

Please determine who is responsible for the bug (and where it should be reported) using this procedure:

  1. If the error message contains text similar to
    java.lang.Error: NullnessSubchecker processor threw unexpected exception when processing MyFile.java
    then the problem is with the annotation processor. Report the bug to the author of the annotation processor, such as the Checker Framework developers.
  2. Try to reproduce the error without using an annotation processor. If you cannot reproduce the error, then the problem may be due to the annotation processor. Report the bug to the author of the annotation processor, such as the Checker Framework developers.
  3. Try to reproduce the error using the OpenJDK compiler, without the Type Annotations enhancements.
    1. Obtain a copy of the OpenJDK compiler, using the commands in the diff section of this document.
    2. Try your test case using the OpenJDK compiler.
    3. If you can reproduce the problem, then search the bug database (use the “Java” category). If the problem is in the bug database, then vote for it. If the problem is not in the bug database, then report your bug to Oracle, using category “Java” and subcategory “compiler”.

If the problem is present in the Type Annotations compiler, but not in the OpenJDK compiler, then please report it to us by creating a new issue in the issue tracking system. (Search the issue tracker first, to avoid reporting a duplicate. But feel free to augment an existing issue with more information.) The issue tracker is not intended for general support or questions.

How can you make a clear, complete bug report?

Please ensure that your bug report is clear and that it is complete. Otherwise, we may be unable to understand it or to reproduce it, either of which would prevent us from fixing the bug. Oracle has a description of how to write a helpful bug report. Here are some crucial points:

Thanks for reporting a bug

Finally, thanks for reporting the bug!

Credits

The Type Annotations compiler was implemented by Matthew M. Papi and Mahmood Ali as a modification of the Oracle OpenJDK compiler. See above for how to report bugs.

Changelog

Differences from previous versions may be found in the changelog.

Making a release (a distribution)

The Type Annotations compiler and the Checker Framework are typically released together; one set of instructions releases both. See file checker-framework/release/README-maintainers.html in the Checker Framework. See that file also for information about the different repositories available in the jsr308-langtools project and about other development practices.


JSR 308 webpage