Transcript Document
Java Annotations for
Invariant Specification
RICE UNIVERSITY
COMPUTER
SCIENCE
Mathias Ricken
September 22, 2008
COMP 617 Seminar
1
Comments are dumb
class HashMap {
// returns null if no mapping for key
Object get(Object key) { … }
}
HashMap m = new HashMap();
Object o = m.get("foo");
String s = o.toString();
NullPointerException at runtime:
o is null
2
Types are smart
class HashMap {
// returns null if no mapping for key
Object|null get(Object key) { … }
}
Compiler Error:
Return type Object|null
HashMap m = new HashMap();
incompatible with type
Object
Object o = m.get("foo");
String s = o.toString();
This is not Java!
3
Annotations can make Java smarter
class HashMap {
// returns null if no mapping for key
@Nullable Object get(Object key) { … }
}
HashMap m = new HashMap();
Compiler Warning:
Return value may be null,
assigned to non-null variable.
Object o = m.get("foo");
String s = o.toString();
Pluggable type systems in Java 5 7?
4
Annotation Targets in Java 5
@A package some.package.name;
@B class MyClass {
@NonNull Object field;
@C MyClass(@NonNull Object param) {
field = param;
}
@NonNull Object method() {
@NonNull Object localVar = field;
return localVar;
}
}
Note:
Local variable annotations are completely ignored.
5
Concurrency Invariants
interface TableModel {
// may only be called from event thread
void setValueAt(…);
}
TableModel m;
// from outside event thread…
m.setValueAt(…);
Possible race condition.
6
Invariant Specification
interface TableModel {
@OnlyEventThread
void setValueAt(…);
}
TableModel m;
// from outside event thread…
m.setValueAt(…);
Invariant Violation Warning at Runtime
(but still possible race condition)
7
Comparison to assert
void setValueAt(…) {
assert (EventQueue.isDispatchThread());
…
Similarity
Debug mode – disabled in production code
@OnlyEventThread
void setValueAt(…) { … }
8
Annotations are Easier to Find
Javadoc produces invariant index
9
Inherited Invariants
TableModel
Object getValueAt(…)
@OnlyEventThread void setValueAt(…)
Implied
@OnlyEventThread
AbstractTableModel
Object getValueAt(…)
void setValueAt(…)
DefaultTableModel
Object getValueAt(…)
void setValueAt(…)
Implied
@OnlyEventThread
MySpecialTableModel
Object getValueAt(…)
void setValueAt(…)
Implied
@OnlyEventThread
10
Inherited Invariants
@OnlyEventThread TableModel
Object getValueAt(…)
void setValueAt(…)
Implied
@OnlyEventThread
AbstractTableModel
Object getValueAt(…)
void setValueAt(…)
DefaultTableModel
Object getValueAt(…)
void setValueAt(…)
Implied
@OnlyEventThread
Implied
@OnlyEventThread
MySpecialTableModel
Object getValueAt(…)
void setValueAt(…)
Implied
@OnlyEventThread
11
Limited Universality
A few supplied invariant annotations
@OnlyEventThread
@OnlyThreadWithName
@OnlySynchronizedThis
@NotEventThread
@NotThreadWithName
@NotSynchronizedThis
assert can test an arbitrary predicate
assert (someComplexPredicate());
12
Predicate Invariant Annotations
@PredicateLink(value=Predicates.class, method="eval")
public @interface OnlyThreadWithName {
String value;
}
1.
@OnlyThreadWithName("main")
void myMethod() { … }
Return true or false
to indicate violation
3.
2.
Call predicate method and
pass as arguments:
• this (nor null if static)
• data in invariant annotation
public class Predicates {
public static boolean eval(Object this0, String name) {
return Thread.currentThread().getName().
equals(name);
}
}
13
Further Limitation of Annotations
One occurrence of an annotation class per
target
@OnlyThreadWithName("main") // illegal; and is
@OnlyThreadWithName("other") // this "and" or "or"?
void myMethod() { … }
Suggestion
@Or({
@OnlyThreadWithName("main"),
@OnlyThreadWithName("other")
})
void myMethod() { … }
14
Annotation Members
extends OtherAnnotation
not allowed no subtyping
@interface MyAnnotation {
int
String
Class
SomeEnum
intMember;
stringMember;
classMember;
enumMember;
//
//
//
//
primitives
strings
class literals
enums
// annotions
OnlyThreadWithName annotMember;
// arrays of the above
OnlyThreadWithName[] arrayMember;
}
15
No Annotation Subtyping in Java
@interface Or { OnlyThreadWithName[] value; }
@Or({@OnlyThreadWithName("main"),
@OnlyThreadWithName("other")})
void myMethod() { … } // legal
@Or({@OnlyThreadWithName("main"),
@NotThreadWithName("other")})
void otherMethod() { … } // illegal
No
common supertype for annotations
16
xajavac Modified Compiler
@interface Base {}
@interface OnlyThreadWithName extends Base {
String value;
}
@interface NotThreadWithName extends Base {
String value;
}
@interface Or extends Base {
Base[] value;
}
17
Results
Annotations with Subtyping
Minimal
changes to the compiler
No changes to class file format
Reduced invariant checker by ~1500 lines
Improved code reuse
18
Results
Invariant Annotations
Annotated
part of Swing and DrJava
Discovered and fixed some bugs in DrJava
Hard to do retroactively and without inside
knowledge
19
Future Work
Reflection library for annotations with
subtyping
Annotation
getAnnotation(Class c)
currently returns the annotation of class c
Annotation[]
getAnnotations(Class c)
should be added to return all annotations of
class c and its subclasses
Modify JSR 308 prototype compiler to
support subtyping
20
More Information and Download
Invariant Specification
http://www.concutest.org/tc/
Annotations with Subtyping
http://www.cs.rice.edu/~mgricken/research/xajavac/