@Documented @Retention(value=RUNTIME) @Target(value={METHOD,CONSTRUCTOR}) public @interface RegionEffects
@RegionEffects("reads readTarget
, ... ; writes writeTarget, ... ")
The annotation contains reads and writes clauses
that each have a list of one or more targets. The reads clause
describes the data that may be read by the method/constructor; the
writes clause describes the state that may be read or written by
the method/constructor. Because writing includes reading, there is no need to
list a target in the reads clause if its state is already
described in the writes clause.
Both the reads and writes clauses are optional: to
indicate that there are no effects use
@RegionEffects("none"). An unannotated method is assumed to
have the annotation @RegionEffects("writes All") which
declares that the method could read from or write to any state in the
program.
A target is an extrinsic syntactic mechanism to name references to regions, and can be one of
this:RegionName (see below). If RegionName is a static
region, it must be a region declared in the annotated class or one of its
ancestors, and is thus a short hand for pkg.C:RegionName below.
pkg.C is an "outer class" of the class that contains the
annotated method. That is, the method being annotated is in class
D, and D is an inner class of C.
Region is a region of pkg.C.
pkg.C is a class name and
RegionName is a region of pkg.C.
static region of
class pkg.C.
final fields produce no effects and do not need to be
declared.Instance
region of the object under construction.Unique and UniqueInRegion) is
taken into account.
@RegionEffects("writes list:Instance")
public void eraseList(List<?> list) {
list.clear();
}
could have used arg0 instead of list as shown below.
@RegionEffects("writes arg0:Instance")
public void eraseList(List<?> list) {
list.clear();
}
Naming arguments by position is mostly used when annotating library methods using XML.
RegionEffects if all possible executions read and write only to the
state specified in the annotation.
At runtime, a target—like a region—represents a subset of the JVM heap, subdividing one or more objects in the heap. While in most cases a target is equivalent to particular runtime region, the any instance target refers to state that is not possible to name with any single region.
RegionName of the object
o referenced by the method/constructor's receiver.
RegionName of the object
o referenced by the parameter p
at the start of the method's execution.
RegionName of the object
o referenced by the qualified receiver pkg.C.this.
T and T instanceof pkg.C. The target
denotes the union of the runtime regions RegionName of each
o ∈ X
static region
RegionName declared in class pkg.C.
@Region("public ValueRegion")
public class Var {
@InRegion("ValueRegion")
private int value;
@RegionEffects("none")
public Var(int v) {
value = v;
}
@RegionEffects("reads ValueRegion")
public int getValue() {
return value;
}
@RegionEffects("writes ValueRegion")
public void setValue(int v) {
value = v;
}
}
Here is an example that uses the pre-defined Static region.
@Utility
public class CounterUtility {
private static long count = 0;
@RegionEffects("writes Static")
public static long incrementAndGet() {
return ++count;
}
@RegionEffects("reads Static")
public static long get() {
return count;
}
private CounterUtility() {
// no instances
}
}
This is another approach to the above example using a named static region.
package com.surelogic;
import com.surelogic.*;
@Utility
@Region("static public CounterState")
public class CounterUtility {
@InRegion("CounterState")
private static long count = 0;
@RegionEffects("writes CounterState")
public static long incrementAndGet() {
return ++count;
}
@RegionEffects("reads CounterState")
public static long get() {
return count;
}
private CounterUtility() {
// no instances
}
}
Here is some client code of the counter class referencing the static
CounterState region.
package com.surelogic;
import com.surelogic.RegionEffects;
public class ClientCode {
@RegionEffects("writes com.surelogic.CounterUtility:CounterState")
public static void main(String[] args) {
long counter = CounterUtility.incrementAndGet();
}
}
@annotate tag.
/**
* @annotate Region("public ValueRegion")
*/
public class Var {
/**
* @annotate InRegion("ValueRegion")
*/
private int value;
/**
* @annotate RegionEffects("none")
*/
public Var(int v) {
value = v;
}
/**
* @annotate RegionEffects("reads ValueRegion")
*/
public int getValue() {
return value;
}
/**
* @annotate RegionEffects("writes ValueRegion")
*/
public void setValue(int v) {
value = v;
}
}
public abstract String value
"none" to indicate that the
method/constructor has no visible effects or divided into separate (and
optional) reads and writes clauses. Each clause is a list of
comma-separated targets describing the regions that may be read/written.
The clauses are separated by a semicolon.
@RegionEffects("reads this:Instance; writes other:Instance")
@RegionEffects("writes C:StaticRegion, any(D):Instance; reads this:Instance")
@RegionEffects("reads this:Instance")
@RegionEffects("writes Instance")
@RegionEffects("writes Static")
@RegionEffects("none")
The value of this attribute must conform to the following grammar (in Augmented Backus–Naur
Form):
value =
none / ; No effects
readsEffect [";" writesEffect] /
writesEffect [";" readsEffect]
readsEffect = "reads" effectsSpecification
writesEffect = "writes" effectsSpecification
effectsSpecification = "nothing" / effectSpecification *("," effectSpecification)
effectSpecification =
simpleEffectExpression ":" simpleRegionSpecification /
IDENTIFIER ; instance region of "this" or a static region declared in the current class or one of its ancestors
simpleEffectExpression =
"any" "(" namedType ")" / ; any instance
namedType "." "this" / ; qualified this expression
namedType / ; class name
simpleExpression ; parameter name
namedType = IDENTIFIER *("." IDENTIFIER)
simpleExpression = "this" / IDENTIFIER
simpleRegionSpecification = IDENTIFIER ; Region of the class being annotated
IDENTIFIER = Legal Java Identifier
Copyright © 2012 Surelogic, Inc.. All Rights Reserved.