25
User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab http://pag.csail.mit.edu/jsr308/

User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Embed Size (px)

Citation preview

Page 1: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

User-defined type checkers for error detection and prevention

in JavaMichael D. Ernst

MIT Computer Science & AI Lab

http://pag.csail.mit.edu/jsr308/

Page 2: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Code without type qualifiers

class DAG { Set<Edge> edges;

// ...

List<Vertex> getNeighbors( Vertex v) { List<Vertex> neighbors = new LinkedList<Vertex>(); for (Edge e : edges) if (e.from() == v) neighbors.add(e.to()); return neighbors; }}

Page 3: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

@NonNull type qualifier@NonNullDefaultclass DAG { Set<Edge> edges;

// ...

List<Vertex> getNeighbors( Vertex v) { List<Vertex> neighbors = new LinkedList<Vertex>(); for (Edge e : edges) if (e.from() == v) neighbors.add(e.to()); return neighbors; }}

Page 4: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

@NonNull type qualifier@NonNullDefaultclass DAG { @NonNull Set<@NonNull Edge> edges;

// ...

@NonNull List<@NonNull Vertex> getNeighbors( @NonNull Vertex v) { List<Vertex> neighbors = new LinkedList<Vertex>(); for (Edge e : edges) if (e.from() == v) // OK neighbors.add(e.to()); // OK return neighbors; }}

Page 5: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

@Interned type qualifier@NonNullDefaultclass DAG { Set<Edge> edges;

// ...

List<Vertex> getNeighbors(@Interned Vertex v) { List<Vertex> neighbors = new LinkedList<Vertex>(); for (Edge e : edges) if (e.from() == v) // OK neighbors.add(e.to()); return neighbors; }}

Page 6: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

@ReadOnly type qualifier@NonNullDefaultclass DAG { Set<Edge> edges;

// ...

List<Vertex> getNeighbors(@ReadOnly Vertex v) @ReadOnly { List<Vertex> neighbors = new LinkedList<Vertex>(); for (Edge e : edges) if (e.from() == v) neighbors.add(e.to()); return neighbors; }}

Page 7: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Using a checker

• Write annotations on the code– Or use an inference tool

• Compiler plugin for javac javac -processor NonnullChecker MyFile.java

• Produces additional errors and warnings– All existing Java checks are performed

• Type-system-specific checks– For NonNull: dereferences– For Interned: equality

• Error to assign supertype to subtype: myObject = myNonNullObject; // OK myInternedObject = myObject; // error myObject = myReadOnlyObject; // error

– Similarly for arguments, returns, overriding, …

Page 8: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Outline

• NonNull checker

• Interned checker

• Javari checker

• IGJ checker

• Creating your own checker

Page 9: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

NonNull checker

• Problem: NullPointerExceptions• Example:

Object obj; // might be null

@NonNull Object nnobj; // never null

nnobj.toString(); // OK

obj.toString(); // possible NPE

obj = ...; // OK

nnobj = obj; // nnobj may become null

• Type system:

Page 10: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

NonNull case study

• Programs:– Annotation file utilities (5 KLOC)– Lookup (4 KLOC, twice)– NonNull checker (1 KLOC)– Checkers framework (5 KLOC)

• Two different defaults: NonNull and Nullable

• Annotations with & without checker available

Page 11: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

NonNull results

• 1 annotation per 50 lines of code– Inference tools exist (for NonNull and other qualifiers)

• 44 errors– if (x.y().z()) { somethingOptional(); }

where no work need be done if x.y() is null

• 83 application invariants– @NonNull indicates whether a variable may be null– @NonNull cannot indicate conditions that hold when a

variable is null• entry_re == null iff exit_re == null

• 43 tool weaknesses (many already fixed)

Page 12: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Comparison with other tools

Program to be checked: Lookup (4KLOC)

Other tools also find non-NPE bugs

To reduce false positives, they discard many warnings

Our checker 7 errors (every error!) 7 false pos.

FindBugs 1 warning: dead code 1 false pos.

JLint 0 8

PMD 0 0

Page 13: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Good defaults reduce user effort

• Nullable default:– Dictated by backward compatibility– Many instances of @NonNull – too verbose– Flow-sensitive analysis inferred many NonNull types

for local variables, reducing annotation burden• NonNull default

– Less verbose in signatures• Draws attention to exceptions rather than the rule

– More annotations in method bodies• Our system: Nullable only for local variables

– Not for generics on local variables– An alternative to type inference; effect may be similar

Page 14: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Interned checker

• Interning (aka hash-consing, canonicalization) chooses a canonical representative– Saves memory– Permits use of == for comparisons

• Problem: Equality errors• Example:

String s;@Interned String is, is2;... is = myString.intern() ... // OKif (is == is2) { ... } // OKif (s == is) { ... } // unsafe equalityis = s; // unsafe assignment

Page 15: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Interned case study

• Program: Daikon (250 KLOC)– Daikon’s key scalability problem is memory– 1170 lines of code/comment refer to interning

• 72% of files have none, 87% have 0, 1, or 2

– 200 run-time assertions– Emacs plug-in for String equality checking

• 127 annotations in 11 files (12KLOC)

Page 16: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Interned results

• 9 errors– Missing calls to intern

• 2 performance bugs– Unnecessary interning in inner loop of file reading

• 1 design flaw– VarInfoName is not interned within its implementation,

but all escaping objects are– Too hard to understand complex interning

• 14 false positives (used @SuppressWarnings)

Page 17: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Javari checker

• Problem: Unintended side effects (mutations)• Example:

<E> List<E> sort(@ReadOnly List<E> arg) { ... // swap two elements E tmp = arg.get(i); arg.put(i, arg.get(j)); // illegal mutation arg.put(j, tmp); // illegal mutation}

• Type system:

Page 18: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Javari case study

• Programs (8KLOC)– JOlden benchmarks– Javari checker– Some JDK classes

Page 19: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Javari results

• Mutability bug in Javari checker– Global variable indicating checker state was

set on entering an inner class, not reset on exiting

– The bug-fix allocates a new object instead

• 3 false positives due to varargs– void format(Object...) { … }

Page 20: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

IGJ checker

• Problem: Unintended side effects (mutations)• Type system:

– ReadOnly: Reference immutability (aliases may modify)– Immutable: Object immutability (object cannot change)

• Syntax uses annotations, not generics

Page 21: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

IGJ case study

• Programs (128KLOC)– JOlden benchmarks– htmlparser library– tinySQL library– SVNKit subversion client– IGJ checker

• 4760 annotations (62133 possible locations)

Page 22: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

IGJ results

• Representation exposure errors• Constructors that left object in inconsistent state• 26 false positives (arrays, varargs, casting)• In SVNKit:

– some getters have side effects– some setters have no side effects

• Used both reference and object immutability• Preferred Annotation IGJ to original dialect: arrays, and

– List<ReadOnly, Date<Mutable>>– @ReadOnly List<@Mutable Date>

• More opportunities for immutability in new code than old

Page 23: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Writing your own checker

• Base checker performs all standard checks (assignment, method arguments)

• Override only a couple methods, for special rules– For NonNull: dereferences– For Interned: equality

• Check what you want:– General properties (tainting)– Project-specific (string formatting)

Page 24: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

JSR 308: Annotation on Java types

• Permits annotations in new locationsList<@NonNull String> myList;

class Properties extends @Immutable Map {…}

• Planned for inclusion in Java 7• Implementation is backwards compatible:

– Write annotations in comments:

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

/*@NonNull*/ String s;– Compiles with any Java compiler

Page 25: User-defined type checkers for error detection and prevention in Java Michael D. Ernst MIT Computer Science & AI Lab

Pluggable type system benefits

• Easy to use• Scalable• Reveals errors• Prevents even more errors

• Download the checkers from http://pag.csail.mit.edu/jsr308/– Prerelease of annotation extensions in Java 7

• Backward-compatible implementation– Includes inference tools for some type checkers– Includes a framework for writing new checkers