Learning Center
Plans & pricing Sign in
Sign Out
Get this document free

Compile-time Type-checking for Custom Type Qualifiers in Java


									     Compile-time Type-checking for Custom Type Qualifiers in Java

                                                 Matthew M. Papi    Michael D. Ernst
                              MIT Computer Science and Artificial Intelligence Lab, Cambridge, MA, USA

Abstract                                                            system includes features that are planned for inclusion in
We have created a system that enables programmers to add            Java 7 (under JSR 308), and it is backward-compatible with
custom type qualifiers to the Java language in a backward-           Java 5.
compatible way. The system allows programmers to write                 In addition, we have developed type-checkers for sev-
type qualifiers in their programs and to create compiler plug-       eral type qualifiers that are useful to programmers. One of
ins that enforce the semantics of these qualifiers at compile        these qualifiers, NonNull, provides an implicit subtype of
time. The system builds on existing Java tools and APIs, and        each Java type that excludes the value null (i.e., a reference
on JSR 308.                                                         whose type is NonNull can never be null). Another, Interned,
   As an example, we introduce a plug-in to Sun’s Java              provides an implicit subtype denoting that a variable may
compiler that uses our system to type-check the NonNull             be safely tested using the == operator (versus the equals
qualifier. Programmers can use the @NonNull annotation               method). A third [4] implements the Javari [5] language. A
to prohibit an object reference from being null; then, by           fourth implements the IGJ [6] language.
invoking a Java compiler with the NonNull plug-in, they
can check for NonNull errors at compile time and rid their
                                                                    2.   Motivation
programs of null-pointer exceptions.                                Types help to detect and prevent errors by helping program-
                                                                    mers to organize and document data, and by allowing tools
Categories and Subject Descriptors D3.3 [Programming
                                                                    like compilers to check that a program does not violate the
Languages]: Language Constructs and Features—data types
                                                                    type system’s constraints. However, in languages like Java,
and structures; F3.1 [Logics and Meanings of Programs]:
                                                                    there is often much information about a type that a program-
Specifying and Verifying and Reasoning about Programs;
                                                                    mer cannot express.
D1.5 [Programming Techniques]: Object-oriented Program-
                                                                       For instance, suppose a programmer wishes a variable
                                                                    to have the type “non-negative integer”. The variable can
General Terms Languages, Theory                                     be declared with the type int, but there is ordinarily no
Keywords annotation, compiler, Java, javac, NonNull, type           mechanism for expressing “non-negative”. A custom type
qualifier, type system, verification                                  qualifier solves this problem: the programmer could use our
                                                                    tools to create a NonNegative qualifier and checker.
1.    Introduction
                                                                    3.   Implementation
We have created a system for adding new type qualifiers to
the Java language and enforcing their semantics at compile          Our system consists of two components.
time. Our system provides a framework that extends existing             The first component of the system, the extended annota-
Java APIs to facilitate compile time type-checking; it builds       tions compiler, is an implementation of the JSR 308 spec-
upon JSR 308 [3]. JSR 308 extends the syntax for Java               ification [3]. It is composed of modifications to the javac
annotations [1] so that they may be written anywhere that           Java compiler for parsing and compiling annotations on Java
types are used, and extends the Java class file format so            types. Java annotations are normally permitted on the decla-
that these annotations are represented in the class file. The        rations of classes, methods, and variables; the extended an-
                                                                    notations compiler permits them anywhere types are written,
                                                                    including typecasts, type tests (instanceof), object cre-
                                                                    ation expressions (new), method receivers, method throws
                                                                    clauses, generic type arguments, multidimensional arrays,
                                                                    type parameter bounds, and class literals. Moreover, the ex-
                                                                    tended annotations compiler can write all annotations to
Copyright is held by the author/owner(s).
OOPSLA’07, October 21–25, 2007, Montr´ al, Qu´ bec, Canada.
                                          e  e
                                                                    the class file in a backward compatible way. This permits
ACM 978-1-59593-786-5/07/0010.                                      type-checking against binary versions of annotated classes
     Cause                                         Errors          class of errors, user errors, are those for which the program-
     User type errors                                   3          mer’s conception of a type was incorrect (i.e., thinking that
     User omissions                                    31          a type was NonNull when it was possibly-null). These are
     Run-time checks (application invariants)          23          serious errors that may lead to null-pointer exceptions at run
     Tool weaknesses                                   15          time. The second class of errors, user omissions, are those in
       Incomplete flow-sensitivity                       8          which the programmer forgot to write a @NonNull annota-
       No qualified generic type inference               7          tion for a NonNull type; they are easily fixed. The third class
                                                                   of errors, run-time checks, are those in which a possibly-null
Table 1. Causes for errors issued by the NonNull type-             type but could be safely used as NonNull at certain locations
checker plug-in during the case study.                             where an application-specific invariant guarantees that the
                                                                   value is not null. We suppressed errors of this type by adding
                                                                   a run-time assertion (e.g., assert x!=null;) for each appli-
(e.g., an annotated library) and will facilitate type-checking
                                                                   cation invariant. The final class of errors, tool weaknesses,
of Java bytecode. The extended annotations compiler also
                                                                   are those for which it was necessary to add an explicit null
parses annotations written in C-style comments (/* */), so
                                                                   check to the subject code to satisfy the type-checker. We ex-
that code can be written for both the extended annotations
                                                                   pect that improvements to the flow-sensitive analysis and in-
compiler and older Java compilers.
                                                                   ference for qualified generic types will eliminate this final
    The system’s second component, the checkers frame-
work, extends Java’s annotation processing API [2] for
                                                                      Using the framework described in Section 3, the NonNull
compile-time type-checking of type qualifier annotations.
                                                                   type-checker consists of only 300 lines of Java source code
The framework provides several features that reduce the
                                                                   (including comments), plus an additional 474 lines for the
time and effort required to create a new type-checker. First,
                                                                   flow-sensitive analysis.
it provides data structures for querying the annotations on a
program element regardless of whether that element is found
in a source file or in a class file. Second, it provides a tem-
plate (using the visitor design pattern) for applying a type       The NonNull type-checker plug-in, the other three plug-ins
qualifier’s rules to an input program, and it interfaces this       mentioned in Section 1, the checkers framework, and the
component to the Java compiler. Third, the framework uses          JSR 308 extended annotations Java compiler are publicly
the Java compiler’s messaging interface for reporting and          available for download from the JSR 308 web site, http:
collecting errors during type checking. Finally, the frame-        //
work provides additional utilities for qualifiers that are either
subtypes or supertypes of the unqualified type. For instance,       References
NonNull and Interned types are subtypes of their unqualified        [1] Gilad Bracha. JSR 175: A metadata facility for the Java
types, and ReadOnly types are supertypes of their unquali-             programming language.
fied types.                                                             id=175, September 30, 2004.
    Individual type-checkers may also include extra fea-           [2] Joe Darcy. JSR 269: Pluggable annotation processing API.
tures beyond those provided by the checkers framework.       , May 17, 2006.
The NonNull type-checker includes a flow-sensitive anal-                Public review version.
ysis that performs limited NonNull inference after explicit        [3] Michael D. Ernst and Danny Coward. JSR 308: Annotations
null checks.                                                           on Java types.,
                                                                       October 17, 2006.
4.   Case study                                                    [4] Telmo Luis Correa Jr., Jaime Quinonez, and Michael D. Ernst.
In order to demonstrate that the current implementation is             Tools for enforcing and inferring reference immutability in
both usable and effective, we have conducted a case study              Java. In OOPSLA Companion, October 2007.
in which we ran the NonNull checker on the NonNull-                [5] Matthew S. Tschantz and Michael D. Ernst. Javari: Adding
annotated source code for a library. The library, which pro-           reference immutability to Java. In OOPSLA, pages 211–230,
vides routines for working with an “index file” that describes          October 2005.
the type qualifiers in a class, consists of 4,640 lines of source   [6] Yoav Zibin, Alex Potanin, Mahmood Ali, Shay Artzi, Adam
code and contains 699 @NonNull annotations (out of 3,700                  z
                                                                       Kie˙ un, and Michael D. Ernst. Object and reference im-
locations where a @NonNull annotation may have been writ-              mutability using Java generics. In ESEC/FSE, September
ten). The library author (who is not an author of this paper)          2007.
added the annotations manually and without the aid of the
NonNull type-checker (before the checker was written).
   Table 1 shows the errors and warnings that resulted from
running the type-checker on the annotated library. The first

To top