@Documented @Retention(value=RUNTIME) @Target(value={TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER,LOCAL_VARIABLE}) public @interface Vouch
This annotation is trusted, i.e., it is not verified.
When used on a type, method, or constructor declaration, the
Vouch annotation requires a brief programmer explanation for the
vouch being made (via the value attribute).
When used on a field, parameter, or local variable declaration, the
value attribute is constrained to be one of the following:
Containable. It is a modeling error if the type of the field is
primitive. It is also a modeling error if the reference type is explicitly
annotated NotContainable.final. It is a modeling error if the field is declared to be
finalImmutable. It is a
modeling error if the type of the field is primitive. It is also a modeling
error if the reference type is explicitly annotated Mutable.ThreadSafe. It is a
modeling error if the type of the field is primitive. It is also a modeling
error if the reference type is explicitly annotated NotThreadSafe.value attributes of the Vouch
annotation listed above is used the reason attribute is used to
capture the programmer explanation for the vouch.
Note that Vouch serves a different role than Assume. Vouches
made by the programmer are typically applied in situations where a static
verification tool, such as JSure, is unable to verify the programmer's
implementation to be consistent with the expressed model. For example, due
the fundamental limitations of static program analysis imposed by Rice's theorem or
because the programmer is unwilling, perhaps due to an organizational
constraint of some sort, to refactor the implementation to facilitate a
static verification. In contrast, assumptions are used to express an
expectation by the programmer about the evolving model—irrespective of
whether or not the expectation can be verified.
init method is used to set state,
perhaps due to an API restriction about using constructors, and then
CentralControl instances are safely published. A Vouch is
used to explain that the init method needs to be an exception to the
lock policy.
@Region("private ControlRegion")
@RegionLock("ControlLock is lock protects ControlRegion")
public class CentralControl {
private final Object lock = new Object();
@InRegion("ControlRegion")
private String f_id;
@Vouch("Instances are thread confined until after init(String) is called.")
public void init(String id) {
f_id = id;
}
public String getId() {
synchronized (lock) {
return f_id;
}
}
public void setId(String value) {
synchronized (lock) {
f_id = value;
}
}
}
A Vouch is used to explain that the SmokeTest class is test
code.
@Vouch("Test code that is intentionally inconsistent with models")
public class SmokeTest extends ... {
...
}
A Vouch is used to explain that a class is using the cheap
read-write lock trick described by Goetz. Without the Vouch the read of the value field in
the getValue method would be reported to be inconsistent with the
declared locking policy.
@ThreadSafe
public class Counter {
// Employs the cheap read-write lock trick
// All mutative operations MUST be done with the "this" lock
@GuardedBy("this")
private volatile int value;
@Vouch("cheap read-write lock trick")
public int getValue() {
return value;
}
public synchronized int increment() {
return value++;
}
}
A @Vouch("Immutable") annotation is used to express
that a list made unmodifiable by invoking
Collections.unmodifiableList(java.util.List) is immutable after
object construction. The use of Vouch is necessary in this example
because, in general, List instances are mutable.
@Immutable public class KeyTimes implements Iterable{ @Vouch("Immutable") private final List<Double> f_keyTimes; private KeyTimes(double... times) { final List<Double> timesList = new ArrayList (); // fills in the collection from the passed varargs ... f_keyTimes = Collections.unmodifiableList(timesList); } ... }
The same example, but with an explanation for the vouch explicitly captured in the annotation
@Immutable public class KeyTimes implements IterableA @Vouch("Immutable") annotation is used to express that a private array is immutable after object construction. Because the Java language does not allow the programmer to express that the contents of the array are unchanging, use of a{ @Vouch(value="Immutable", reason="Initialized with an immutable list via Collections.unmodifiableList()") private final List<Double> f_keyTimes; private KeyTimes(double... times) { final List<Double> timesList = new ArrayList (); // fills in the collection from the passed varargs ... f_keyTimes = Collections.unmodifiableList(timesList); } ... }
Vouch is necessary in this example.
@Immutable
public class Aircraft {
@Vouch(value="Immutable",
reason="Initialized in the constructor; immutable thereafter")
private final Wing[] f_wings;
public Aircraft() {
f_wings = new Wing[2];
f_wings[0] = new Wing();
f_wings[1] = new Wing();
}
...
}
A @Vouch("ThreadSafe") annotation is used to express
that a list made unmodifiable by invoking
Collections.synchronizedList(List) is thread-safe . The vouch is
necessary because, in general, List instances are not thread-safe.
@ThreadSafe
public class KeyValues<T> {
@Vouch("ThreadSafe")
private final List<T> f_values;
private KeyValues(List<T> values) {
f_values = Collections.synchronizedList(values);
}
...
}
The below example, which is a highly questionable protocol, sets the lock
once after object construction and uses
@Vouch("final") to state this policy.
@Region("private BadFinalRegion")
@RegionLock("BadFinalLock is lock protects BadFinalRegion")
public class BadFinal {
@Vouch("final")
private Object lock;
// Called only once at startup
public void setLock(Object value) {
lock = value;
}
...
@InRegion("BadFinalRegion")
private int x, y;
public void tick() {
synchronized (lock) {
x++;
y++;
}
}
...
}
An improved implementation would set the lock via the constructor and avoid
the assumption about the lock reference. In the example below, the
BadFinal code is changed so that the lock field can be declared to be
final (and checked by the compiler).
@Region("private GoodFinalRegion")
@RegionLock("GoodFinalLock is lock protects GoodFinalRegion")
public class GoodFinal {
private final Object lock;
public GoodFinal(Object value) {
lock = value;
}
...
@InRegion("GoodFinalRegion")
private int x, y;
public void tick() {
synchronized (lock) {
x++;
y++;
}
}
...
}
In general, use of @Vouch("final") should be avoided
where it is possible to refactor the code in a manner similar to the example
above.
A @Vouch("AnnotationBounds") annotation is used below to allow Runnable to satisfy the conditional bounds of java.util.ArrayList, so that ArrayList<Runnable> can be considered to be containable. Ultimately this allows the class below to be assured as thread-safe.
@ThreadSafe
@Region("State")
@RegionLock("StateLock is this protects State")
public class VouchContainableCollection {
@Vouch("AnnotationBounds")
@UniqueInRegion("State")
private final ArrayList f_tasks = new ArrayList();
// ...
}
The vouch is necessary because java.lang.Runnable is too
general a class to be annotated as @ThreadSafe or
@ReferenceObject, as it would need to be to satisfy
the conditional bounds required the @Containable
annotation of java.util.ArrayList. In this case, the
programmer is vouching that the Runnable objects are not going to
do anything that would interfere with the containability of the list
object.
@annotate tag.
/**
* @annotate Region("private ControlRegion")
* @annotate RegionLock("ControlLock is lock protects ControlRegion")
*/
public class CentralControl {
private final Object lock = new Object();
/**
* @annotate InRegion("ControlRegion")
*/
private String f_id;
/**
* @annotate Vouch("Instances are thread confined until after init(String) is called.")
*/
public void init(String id) {
f_id = id;
}
...
}
/** * @annotate Immutable */ public class KeyTimes implements Iterable{ /** * @annotate Vouch("Immutable") */ private final List<Double> f_keyTimes; ... }
/**
* @annotate Immutable
*/
public class Aircraft {
/**
* @annotate Vouch("Immutable")
*/
private final Wing[] f_wings;
...
}
/**
* @annotate ThreadSafe
*/
public class KeyValues<T> {
/**
* @annotate Vouch("ThreadSafe")
*/
private final List<T> f_values;
...
}
public class BadFinal {
/**
* @annotate Vouch("final")
*/
private Object lock;
...
}
Assume| Modifier and Type | Required Element and Description |
|---|---|
String |
value
When the annotation applies to a type, method, or constructor then the
value of this attribution must contain a brief programmer explanation of
why the annotated code should have its inconsistent assurance results
suppressed.
|
public abstract String value
When the annotation applies to a vouch with special semantics, then the value of this attribute must conform to the following grammar (in Augmented Backus–Naur Form):
value = "Containable" / "final" / "Immutable" / "ThreadSafe" / "AnnotationBounds"
public abstract String reason
Copyright © 2012 Surelogic, Inc.. All Rights Reserved.