Post on 08-Jan-2016
description
111
The Java Modeling Language
Based on:Gary T. Leavens, et al., JML Tutorial at OOPSLA 2009.Gary. T Leavens, et al., Preliminary Design of JML: A Behavioral
Interface Specification Language for Java, ACM SIGSOFT Software Engineering Notes, 31(3):1-38, May, 2006.
1
222
Outline
• JML overview• Reading and writing JML specifications• Abstraction in specification• Subtyping and specification inheritance
2
333
Overview of JML
• Java Modeling Language (JML)– Formal– Sequential Java– Functional behavior of APIs
• JML’s goals– Practical, effective for detailed designs
• Inter-module interfaces• Classes and interfaces• Data (fields)• Methods
– Existing code– Wide range of tools
3
444
Basic Approach of JML
“Eiffel + Larch for Java”
• Hoare-style (contracts)
• Method pre- and post-conditions
• Invariants
4
555
First JML Specification
public class ArrayOps {
private /*@ spec_public @*/ Object[] a;
//@ public invariant 0 < a.length;
/*@ requires 0 < arr.length; @ ensures this.a == arr;
@*/public void init(Object[] arr) {
this.a = arr;}
5
666
Field Specification with spec_public
public class ArrayOps {
private /*@ spec_public @*/ Object[] a;
//@ public invariant 0 < a.length;
/*@ requires 0 < arr.length; @ ensures this.a == arr;
@*/public void init(Object[] arr) {
this.a = arr;}
6
777
Class Invariant
public class ArrayOps {
private /*@ spec_public @*/ Object[] a;
//@ public invariant 0 < a.length;
/*@ requires 0 < arr.length; @ ensures this.a == arr;
@*/public void init(Object[] arr) {
this.a = arr;}
7
888
Method Specification
public class ArrayOps {
private /*@ spec_public @*/ Object[] a;
//@ public invariant 0 < a.length;
/*@ requires 0 < arr.length; @ ensures this.a == arr;
@*/public void init(Object[] arr) {
this.a = arr;}
8
99
Interface Specification
Java Code
JML Specification
Functional BehaviorSyntactic Interface
1010
Interface Specification
public void init(Object[] arr){ this.a = arr; }
/*@ requires 0 < arr.length; @ ensures this.a == arr; @*/public void init(Object[] arr);
requires 0 < arr.length;ensures this.a == arr;public void init(Object[] arr);
1111
Comparison with Other Formal Specification Languages
• Like … but for Java – VDM, but
• OO features– Eiffel, but
• Features for formal verification– Spec#, but
• Different invariant methodology• More features for formal verification
• Unlike OCL and Z– More Java-like syntax– Tailored to Java semantics
1212
Many Tools, One Language
1313
How JML Tools Complement Each Other
• Different strengths:– Runtime checking — real errors– Static checking — better coverage– Verification — guarantees
• Usual ordering:1. Runtime checker (jmlc and jmlunit)
2. Extended Static Checking (ESC/Java2)
3. Verification tool (e.g., KeY, JACK, Jive)
141414
Outline
JML overview• Reading and writing JML specifications• Abstraction in specification• Subtyping and specification inheritance
14
1515
JML Annotations
• Not Java annotations (starting with @)
• JML annotation comments– Line starting with //@– Between /*@ and @*/, ignoring @’s starting
lines
1616
Most Important JML Keywords
• Top-level in classes and interfaces:– invariant– spec_public– nullable
• For methods and constructors:– requires– ensures– assignable– pure
1717
Example: BoundedStack
• Specify bounded stacks of objects
• Steps1. Data and invariant
2. Constructor
3. Methods like push, pop, and top
1818
BoundedStack’s Data and Invariant
public class BoundedStack {private /*@ spec_public nullable @*/ Object[] elems;
private /*@ spec_public @*/ int size = 0;
//@ public invariant 0 <= size;
/*@ public invariant elems != null @ && (\forall int i; @ size <= i && i < elems.length; @ elems[i] == null); @*/
1919
BoundedStack’s Constructor/*@ requires 0 < n; @ assignable elems; @ ensures elems.length == n; @*/public BoundedStack(int n) {
elems = new Object[n];}
2020
BoundedStack’s push Method/*@ requires size < elems.length - 1; @ assignable elems[size], size; @ ensures size == \old(size + 1); @ ensures elems[size - 1] == x; @ ensures_redundantly @ (\forall int i; 0 <= i && i < size - 1; elems[i] == \
old(elems[i])); @*/public void push(Object x) {
elems[size] = x;size++;
}
2121
BoundedStack’s pop Method/*@ requires 0 < size; @ assignable size, elems[size - 1]; @ ensures size == \old(size - 1); @ ensures_redundantly @ elems[size] == null && @ (\forall int i; 0 <= i && i < size - 1; elems[i] == \
old(elems[i])); @*/public void pop() {
size--; elems[size] = null;
}
2222
BoundedStack’s top Method
/*@ requires 0 < size;
@ assignable \nothing;
@ ensures \result == elems[size - 1];
@*/
public /*@ pure @*/ void top() {
return elems[size – 1];
}
2323
JML Keywords Used
• spec_public– Public visibility– Only public for specification purposes
• nullable– field (and array elements) may be null– Default is non_null
• invariant must be:– True at end of constructor– Preserved by each method (except for helper
methods)
2424
JML Keywords Used
• requires clause:– Precondition– Obligation on callers, after parameter passing– Assumed by implementor
• ensures clause:– Postcondition– Obligation on implementor, at return– Assumed by caller
2525
Semantics of requires and ensures
2626
Semantics of requires and ensures
2727
Semantics of requires and ensures
2828
JML Keywords Used
• assignable– Frame axiom– Locations (fields) in pre-state– New object fields not covered– Mostly checked statically– Synonyms: modifies, modifiable
• pure– No side effects– Implies assignable \nothing– Allows method’s use in specifications
2929
Assignable Is a Shorthand
assignable gender;
ensures gender.equals(g);
means
ensures \only_assigned(gender) && gender.equals(g);
3030
JML Keywords Used
• Redundant clauses (ensures_redundantly)– Alerts reader– States something to prove– Must be implied by:
• ensures clauses,• assignable clause,• invariant, and• JML semantics.
– Also requires_redundantly, etc.
3131
Multiple Clauses
Semantics:
requires P;requires Q;
is equivalent to:
requires P && Q;
Similarly for ensures, invariant.
Note: checkers give more specific messages with multiple clauses.
3232
Defaults for Omitted Clauses
• invariant true;
• requires true;
• assignable \everything;
• ensures true;
3333
Expression Keywords
• \result = method’s return value.• \old(E) = pre-state value of E.• (\forall T x; P; Q) = {Q | x T P}• (\exists T x; P; Q) = {Q | x T P}• (\min T x; P; E) = min{E | x T P}• (\sum T x; P; E) = {E | x T P}• (\num_of T x; P; Q) = {1 | x T P Q}• …
3434
Steps for Specifying a Type for Public Clients
1. Specify data (spec_public fields)
2. Specify a public invariant
3. Specify each public method using:1. requires
2. assignable (or pure)
3. ensures
3535
Exercise
• Specify the following stack methods– int capacity(): capacity of this stack?– int size(): no. of elements?– boolean isEmpty(): has no element?– int search(Object o): 1-based position of given object
in this stack?
private /*@ spec_public nullable @*/ Object[] elems;private /*@ spec_public @*/ int size = 0;
3636
Solution
//@ ensures \result == elems.length;
public /*@ pure *@/ int capacity() { …}
//@ ensures \result == size;
public /*@ pure *@/ int size()() { …}
//@ ensures \result == (size == 0);
public /*@ pure *@/ boolean isEmpty() { …}
private /*@ spec_public nullable @*/ Object[] elems;private /*@ spec_public @*/ int size = 0;
3737
Solution
//*@ ensures (\exists int i; i >= 0 && i < size; elems[i] == o)
? \result > 0 && \result <= size && elems[\result] == o
: \result == 0 @*//
public /*@ pure *@/ int search(Object o) { …}
Q: the first (or last) from the top?
private /*@ spec_public nullable @*/ Object[] elems;private /*@ spec_public @*/ int size = 0;
3838
Exercise: BagOfInt
Specify the following
public class BagOfInt { private int[] a; private int n;
/** Initialize to contain input’s elements. */ public BagOfInt(int[] input);
/** Return the multiplicity of i. */ public int occurrences(int i);
/** Return and delete the minimum element. */ public int extractMin();}
3939
Solution: Data and Constructor
public class BagOfInt { /** Elements. */ private /*@ spec_public non_null @*/ int[] a;
/** Number of active elements in a. */ private /*@ spec_public @*/ int n;
//@ public invariant 0 <= n && n <= a.length;
/** Initialize to contain input’s elements. */ /*@ assignable a, n; @ ensures n == input.length; @ ensures (\forall int i; 0 <= i && i < n; a[i] == input[i]); @*/ public BagOfInt(/*@ non_null @*/ int[] input);
4040
Solution: Methods/** Return the multiplicity of i. *//*@ ensures \result == (\num_of int j; 0 <= j && j < n; a[j] == i); @*/public /*@ pure @*/ int occurrences(int i);
/** Return and delete the minimum element. *//*@ requires 0 < n; @ assignable n, a, a[*]; @ ensures n == \old(n - 1); @ ensures \result == \old((\min int j; 0 <= j && j < n; a[j])); @ ensures (\forall int j; 0 <= j && j < \old(n); @ (\old(a[j]) != \result ==> @ occurrences(\old(a[j])) == \old(occurrences(a[j]))) || @ (\old(a[j]) == \result ==> @ occurrences(\old(a[j])) == \old(occurrences(a[j]) - 1))); @*/public int extractMin();
4141
ExerciseQ: What’s wrong with this and how to fix it?
Hint: Undefinedness
public class ScreenPoint {
private /*@ spec_public @*/ int x, y;
//@ public invariant 0 <= x && 0 <= y;
//@ requires 0 <= cs[0] && 0 <= cs[1]; //@ assignable x, y; //@ ensures x == cs[0] && y == cs[1]; public ScreenPoint(int[] cs) { x = cs[0]; y = cs[1]; }
4242
Solution
A: Undefined expression
public class ScreenPoint {
private /*@ spec_public @*/ int x, y;
//@ public invariant 0 <= x && 0 <= y;
//@ requires 2 <= cs.length; //@ requires 0 <= cs[0] && 0 <= cs[1]; //@ assignable x, y; //@ ensures x == cs[0] && y == cs[1]; public ScreenPoint(int[] cs) { x = cs[0]; y = cs[1]; }
4343
Writing Protective Specifications
• Clauses evaluated left to right• Short-circuit operators can prevent evaluation
– G && P, G || P– G ==> P, G <== P
• Use multiple clauses (equivalent to &&)
44
Multiple Specification Cases
• For different preconditions
• May overlap
• Used to specify exceptions
• Used with specification inheritance
44
4545
Example
private /*@ spec_public @*/ int age;
/*@ requires 0 <= a && a <= 150; @ assignable age; @ ensures age == a; @ also @ requires a < 0 || a > 150; @ assignable \nothing; @ ensures age == \old(age); @*/public void setAge(int a) { if (0 <= a && a <= 150) age = a;}
46
Semantics of Multiple Cases
46
4747
Meaning of “also”
Rewrite to conjoin (frame must be the same).
private /*@ spec_public @*/ int age;
/*@ requires 0 <= a && a <= 150; @ assignable age; @ ensures age == a; @ also @ requires a < 0 || a > 150; @ assignable \nothing; @ assignable age; @ ensures age == \old(age) && only_assigned(\nothing); @*/public void setAge(int a) { if (0 <= a && a <= 150) age = a;}
48
Meaning of “also”
48
requires (0 <= a && a <= 150) || (a < 0 || a > 150);assignable age;ensures \old(0 <= a && a <= 150) ==> (age == a);ensures \old(a < 0 || a > 150) ==> (age == \old(age) && \only_assigned(\nothing));
49
Views of Multiple Cases
• Client can verify by:– Picking one spec case
• Assert precondition
• Assume frame and postcondition
– Picking several cases• Compute their join
• Assert joined precondition
• Assume frame and joined postcondition
• Implementor can:– Verify each case, or– Verify their join
49
50
Specifying Exceptions
• Use features such as– exceptional_behavior spec cases– signals_only clause– signals clause
5151
Examplepublic class Actor {
private /*@ spec_public @*/ int age;
private /*@ spec_public @*/ int fate;
//@ public invariant 0 <= age && age <= fate;
5252
Example/*@ public normal_behavior
@ requires age < fate - 1;
@ assignable age;
@ ensures age == \old(age+1);
@ also
@ public exceptional_behavior
@ requires age == fate - 1;
@ assignable age;
@ signals_only DeathException;
@ signals (DeathException e) age == fate;
@*/
public void older() throws DeathException
5353
Example/*@ public normal_behavior
@ requires age < fate - 1;
@ assignable age;
@ ensures age == \old(age+1);
@ also
@ public exceptional_behavior
@ requires age == fate - 1;
@ assignable age;
@ signals_only DeathException;
@ signals (DeathException e) age == fate;
@*/
public void older() throws DeathException
semantics: signals (Exception)
false;
semantics: ensures false;
Lightweight vs. heavyweight specs: \not_specified as default
5454
Exercise: Using Multiple Cases
Specify the 3x + 1 or “hailstone” function, h, such that:
h(n) = (3 *n + 1)/2, if n > 0 and is odd
n / 2, if n > 0 and is even
and h is undefined on negative numbers.
(Collatz conjecture: you shall always eventually reach 1 by repeating the process.)
5555
Solution/*@ requires 0 < n;
@ requires n % 2 != 0;
@ ensures \result == (3*n+1)/2;
@ also
@ requires 0 < n;
@ requires n % 2 == 0;
@ ensures \result == n/2;
@*/
public static /*@ pure @*/ int h(int n)
5656
Solution Using Nesting/*@ requires 0 < n;
@ {| requires n % 2 != 0;
@ ensures \result == (3*n+1)/2;
@ also
@ requires n % 2 == 0;
@ ensures \result == n/2;
@ |}
@*/
public static /*@ pure @*/ int h(int n)
575757
Outline
JML overviewReading and writing JML specifications• Abstraction in specification• Subtyping and specification inheritance
57
5858
Motivating Example
public class SetOfObject { private /*@ spec_public non_null @*/ Object[] a;
/** Number of active elements in a. */ private /*@ spec_public @*/ int n;
//@ public invariant 0 <= n && n <= a.length;
/*@ public invariant @ (\forall int i; 0 <= i && i < n; @ (\forall int j; 0 <= j && j < n; i != j ==> a[i] != a[j]); @*/
/** Remove the argument from this set. */ public void remove(Object o);
Specify the remove method given below.Q: Meaning of the second invariant?
5959
Solution
/*@ requires (\exists int i; 0 <= i && i < n; a[i] == o); @ assignable n, a, a[*]; @ ensures n == \old(n - 1); @ ensures (\forall int i; 0 <= i && i < \old(n); @ (\old(a[i]) == o ==> !(\exists int j; 0 <= j && j < n; a[j] == o) && @ (\old(a[i]) != o ==> (\exists int j; 0 <= j && j < n; a[j] == o); @*/public void remove(Object o);
Long and hard to read and understand!
Q: How to know the new set has no other elements?
6060
Better Solution
/*@ requires has(o); @ assignable n, a, a[*]; @ ensures n == \old(n - 1); @ ensures (\forall int i; 0 <= i && i < \old(n); @ (\old(a[i]) == o ==> !has(o)) && @ (\old(a[i]) != o ==> has(o)) @*/public void remove(Object o);
//@ ensures \result == (\exists int i; 0 <= i && i < n; a[i] == o);public /@ pure @*/ void has(Object o);
Better but still low level; manipulation of concrete
representation
6161
Solution Using Abstraction
public class SetOfObject { //@ public model JMLObjectSet theSet;
private Object[] a; //@ in theSet; private int n; //@ in theSet;
//@ private represents theSet <- JMLObjectSet.convertFrom(a, n);
/*@ requires theSet.has(o); // o theSet @ assignable theSet; @ ensures theSet.equals(\old(theSet.remove(o))); // theSet’ = theSet – {o} @*/ public void remove(Object o);
Abstract specification using model fields (abstract values)Q: Advantages?
62
Why Use Abstraction in Specification?
• Ease maintenance by information hiding
• Readability:– Avoid quantifiers– Repeated expressions
• Specify when no fields available– Java “interfaces”
63
Features Supporting Abstraction
• model fields and represents clauses
• pure model methods
• pure methods
• protected invariants, spec cases, etc.
• private invariants, spec cases, etc.
• model classes (JMLObjectSet, etc.)
64
Model Fields for Data Abstraction
• Model fields:– Just for specification– Abstraction of Java fields– Value from represents
65
Model Field In an Interface
public interface Gendered {
//@ public model instance String gender;
//@ ensures \result == gender.equals("female");
public /*@ pure @*/ boolean isFemale();
}
Note a new JML modifier instance because it defaults to static in interfaces.
66
Represents Clauses
public class Animal implements Gendered {
protected boolean gen; //@ in gender;
//@ protected represents gender <- (gen ? "female" : "male");
public /*@ pure @*/ boolean isFemale() {
return gen;
}
• Use an in clause to specify a data group.• Protected represents clause (abstraction function).• Specification inheritance.
67
Correctness with Model Fields
68
Example of Using Model Fields
protected boolean gen; //@ in gender;
//@ protected represents gender <- (gen ? "female" : "male");
/*@ requires g.equals("female") || g.equals("male");
@ assignable gender;
@ ensures gender.equals(g); @*/
public Animal(final String g) {
gen = g.equals("female");
}
Q: Is Animal’s constructor (below) correct?
69
Example of Using Model Fields
protected boolean gen; //@ in gender;
//@ protected represents gender <- (gen ? "female" : "male");
/*@ requires g.equals("female") || g.equals("male");
@ assignable gender;
@ ensures gender.equals(g); @*/
public Animal(final String g) {
gen = g.equals("female");
}
Q: Is Animal’s constructor (below) correct?
Yes!
70
Semantics of spec_public
protected /*@ spec_public @*/ int age = 0;
shorthand for:
//@ public model int age;protected int _age = 0; //@ in age;//@ protected represents age <- _age;
and rewriting Java code to use _age.
71
Data Groups for Assignable Clauses
• Each field is a data group
• Membership by in clauses
• Model field’s group contains fields used in its represents
72
Data Groups and Assignable Picture
73
The Semantics of Assignable
assignable x, y;
means:
method only assigns to (concrete) members of DG(x) DG(y).
Q: What does “assignable gender;” mean?
74
In Clauses for Declarations
• private T x; //@ in g;– Immediately follows declaration– Same visibility as declaration
• JML ensures that:– If f DG(g), then g visible where f is.– If f and g visible, can tell if f DG(g).
75
Type-Level Specification Features
• Model fields, in, represents
• invariant
• initially
• constraint
76
Initially Clauses
• Hold in constructor post-states
• Basis for datatype induction
import java.util.*;
public class Patient extends Person {
//@ public invariant 0 <= age && age <= 150;
protected /*@ spec_public @*/ List log;
//@ public initially log.size() == 0;
77
History Constraints
• Relate pre-states and post-states• Justifies inductive step in datatype induction
import java.util.*;
public class Patient extends Person {
protected /*@ spec_public @*/ List log;
/*@ public constraint log.size() >= \old(log.size());
@ public constraint (\forall int i; 0 <= i && i < \old(log.size());
@ log.get(i).equals(\old(log.get(i))));
@*/
78
Exercise
Specify a bounded counter class by writing invariant, initially, and history constraints.
• Start with an initial value 0.• Return to 0 when it reaches the maximum value, 100.
public class BoundedCounter {
private int value;
/** Increment this counter by one. */
public void increment() { …}
79
Helper Methods and Constructors
A helper method or constructor is:
• private
• Exempt from invariants and history constraints– Cannot assume them– Need not establish them
808080
Outline
JML overviewReading and writing JML specificationsAbstraction in specification• Subtyping and specification inheritance
80
81
Problems
• Duplication of specifications in subtypes
• Modular verification when use:– Subtyping, and– Dynamic dispatch
82
Specification Inheritance Approach
Inherit:• Instance fields• Type specifications
– Invariants– Initially clauses– History constraints
• Instance methods• Method specification cases
83
Multiple Inheritance Example
84
Age, NormalSetAge, and ExceptionalSetAge
public interface Age {
//@ model instance int age;
}
public interface NormalSetAge implements Age {
/*@ requires 0 <= a && a <= 150;
@ assignable age;
@ ensures age == a; @*/
public void setAge(int a);
}
public interface ExceptionalSetAge implements Age {
/*@ requires a < 0 || a > 150;
@ assignable \nothing;
@ ensures age == \old(age); @*/
public void setAge(int a);
}
85
What About Animal’s setAge Method?
• It’s both.
• Should obey both specifications.
86
Single Inheritance
public interface Gendered {
//@ ensures \result == gender.equals("female");
public /*@ pure @*/ boolean isFemale();
}
public class Animal implements Gendered {
public /*@ pure @*/ boolean isFemale() {
return gen;
}
}
Q: What is the specification of Animal’s isFemale method?
87
Adding to Specification in Subtype
import java.util.*;
public class Patient extends Person {
protected /*@ spec_public @*/
boolean ageDiscount = false; //@ in age;
/*@ also
@ requires (0 <= a && a <= 150) || (a < 0 || a > 150);
@ ensures 65 <= age ==> ageDiscount; @*/
public void setAge(final int a) {
super.setAge(a);
if (65 <= age) { ageDiscount = true; }
}
Use the “also” keyword.
88
Method Specification Inheritance
/*@ requires 0 <= a && a <= 150;
@ assignable age;
@ ensures age == a;
@ also
@ requires a < 0 || a < 10;
@ assignable age;
@ ensures age == \old(age); @*/
/*@ also
@ requires (0 <= a && a <= 150) || (a < 0 || a > 150);
@ ensures 65 <= age ==> ageDiscount; @*/
Q: What is the extended specification of Patient’s setAge method?A: The join of the 3 spec cases shown previously
/*@ requires 0 <= a && a <= 150;
@ assignable age;
@ ensures age == a;
@ also
@ requires a < 0 || a < 10;
@ assignable age;
@ ensures age == \old(age); @*/
/*@ also
@ requires (0 <= a && a <= 150) || (a < 0 || a > 150);
@ ensures 65 <= age ==> ageDiscount; @*/
Q: What is the extended specification of Patient’s setAge method?A: The join of the 3 spec cases shown previously
89
Avoiding Duplication of Preconditions
/*@ requires 0 <= a && a <= 150;
@ assignable age;
@ ensures age == a;
@ also
@ requires a < 0 || a < 10;
@ assignable age;
@ ensures age == \old(age); @*/
/*@ also
@ requires \same;
@ ensures 65 <= age ==> ageDiscount; @*/
Use \same in the requires clause
909090
Outline
JML overviewReading and writing JML specificationsAbstraction in specificationSubtyping and specification inheritance
90