JML and Class Specifications
description
Transcript of JML and Class Specifications
![Page 1: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/1.jpg)
JML and Class Specifications
• Class invariant• JML definitions• Queue example• Running JML in Eclipse
![Page 2: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/2.jpg)
Review JML Language1. JML specs are comments:/*@ …. @*/
2. The Hoare triple{P} s1; s2; …; sn {Q} is written in JML/Java as:
/*@ requires P ; ensures Q ;@*/type method (parameters) { locals s1; s2; …; sn
}
![Page 3: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/3.jpg)
More JML
![Page 4: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/4.jpg)
Class SpecificationsA class C is formally specified if:
1. Every constructor and public method M in the class has
preconditions and postconditions, and2. C has a special predicate called its class invariant INV
which, for every object o in C, argument x and call o.M(x), must be true both before and after the call.
Note: During a call, INV may temporarily become false.
Why are we doing this???• Formal specifications provide a
foundation for rigorous OO system design (e.g., “design by contract”).
• They enable static and dynamic assertion checking of an entire OO system.
• They enable formal correctness proof of an OO system.
![Page 5: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/5.jpg)
Example: A Simple Queue Class
public class Queue { /* A first-in-first-out queue looks like this:
Node Node |val | |val | |prior| --> |prior| --> ... First
last ... <-- |next | <-- |next | */
private class Node { } private Node first = null;private Node last = null;private int n = 0; public void enqueue(Object v) { }public Object dequeue( ) {}public Object front() {}public boolean isEmpty() {}public int size() {}public void display() {}
}
state variableshelp us defineINVpublicmethods M
public constructor C = Queue()
internal “helper” class
![Page 6: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/6.jpg)
Adding Class-Level Specifications
/*@ public model Node H, T; private represents H <- first; private represents T <- last; public invariant n == size(); @*/private /*@ spec_public @*/ Node first = null;private /*@ spec_public @*/ Node last = null;private /*@ spec_public @*/ int n = 0;
more JML
JML model variablesclass invariant INV
Notes: 1) JML model variables allow a specification to distance itself from the class’s implementation details.2) “spec_public” allows JML specifications to treat a Java variable as public without forcing the code to do the same.
![Page 7: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/7.jpg)
Adding Method Specifications
/*@ ensures T.prior == \old(T) && H.prior == null && T.val.equals(v) ;
@*/public void enqueue(Object v) {
last = new Node(v, last, null);if (first == null) first = last;else (last.prior).next = last;n = n+1;
}
Notes: 1) \old denotes the value of T at entry to enqueue.2) The ensures clause specifies that enqueue adds v to the tail T, and that the head H is not affected.
![Page 8: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/8.jpg)
What specifications for dequeue?
/*@
@*/public Object dequeue( ) {
Object result = first.val;first = first.next;if (first != null) first.prior = null ;else last = null;n = n-1;return result;
}
![Page 9: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/9.jpg)
“Pure” methods
/*@ requires n > 0; ensures \result == H.val && H == \old(H);@*/public /*@ pure @*/ Object front() { return first.val; }
Note: A method is pure if:1) it has no non-local side effects, and2) it is provably non-looping.
![Page 10: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/10.jpg)
Design by Contract Concretized
Obligations Benefits
Client(caller)
Arguments for eachmethod/constructor callmust satisfy its requiresclause
The call delivers correctresult, and the object keepsits integrity
Class(object)
Result for each call mustsatisfy both its ensuresclause and INV
Called method/constructordoesn’ t need extra code tocheck argument validity
Note: Blame can be assigned if obligations aren’ t met!
![Page 11: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/11.jpg)
The contract for the Queue class
Obligations Benefits
Client(caller)
Arguments for every call toQueue(), enqueue,dequeue, front,isEmpty, size, anddisplay
must satisfy its requiresclause
Every call to Queue(), enqueue, dequeue,, front, isEmpty, size, and displaydelivers a correct result,and the object keeps itsintegrity
Class(object)
Result from each call mustsatisfy both its ensuresclause and the class invariantn == size()
No method orconstructor needs extracode to check argumentvalidity
![Page 12: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/12.jpg)
Test driving the Queue class
public class QueueTest { public static void main(String[] args) { Queue q = new Queue(); int val; int n = Integer.parseInt(args[0]); for (int i=1; i <= n; i++) q.enqueue(args[i]); System.out.print("Queue contents = "); q.display(); System.out.println("Is Queue empty? " + q.isEmpty()); System.out.println("Queue size = " + q.size()); while (! q.isEmpty()) { System.out.print(" dequeue " + q.dequeue()); System.out.print(" Queue contents = "); q.display(); } System.out.println("Is Queue empty now? " + q.isEmpty()); }}
![Page 13: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/13.jpg)
Contract test 1: normal run
% jmlrac QueueTest 5 1 2 3 4 5Queue contents = last --> 5 4 3 2 1 <-- firstIs Queue empty? falseQueue size = 5 dequeue 1 Queue contents = last --> 5 4 3 2 <-- first dequeue 2 Queue contents = last --> 5 4 3 <-- first dequeue 3 Queue contents = last --> 5 4 <-- first dequeue 4 Queue contents = last --> 5 <-- first dequeue 5 Queue contents = last --> <-- firstIs Queue empty now? true%
![Page 14: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/14.jpg)
Contract test 2: precondition violation
Queue contents = last --> 1 2 3 4 5 <-- first…dequeue 4 Queue contents = last --> 5 <-- firstdequeue 5 Queue contents = last --> <-- firstException in thread "main" org.jmlspecs.jmlrac.runtime.JMLEntryPreconditionError: by method Queue.dequeue regarding specifications at File "../../home/allen/Desktop/workspace/myQueueTest/myqueuetest/
Queue.java", line 36, character 29 when'this' is myqueuetest.Queue@b166b5at myqueuetest.Queue.checkPre$dequeue$Queue(Queue.java:626)at myqueuetest.Queue.dequeue(Queue.java:771)at myqueuetest.QueueTest.main(QueueTest.java:16)
Note: blame is likely to be with the caller QueueTest, since a precondition has been violated.
![Page 15: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/15.jpg)
Contract test 3: postcondition violation
Note: blame is likely to be with the callee Queue, since a postcondition has been violated.
Queue contents = last --> 5 4 3 2 1 <-- firstIs Queue empty? FalseException in thread "main" org.jmlspecs.jmlrac.runtime.
JMLNormalPostconditionError: by method Queue.dequeue regarding specifications at File "../../home/allen/Desktop/workspace/myQueueTest/myqueuetest/Queue.java", line 37, character 52 when
'\old(H)' is myqueuetest.Queue$Node@b166b5'\result' is 5'this' is myqueuetest.Queue@cdfc9c…
![Page 16: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/16.jpg)
Contract test 4: invariant error
% jmlrac QueueTest 5 1 2 3 4 5Exception in thread "main" org.jmlspecs.jmlrac.runtime.JMLInvariantError: by method Queue.enqueue@post<File "../../home/allen/Desktop/workspace/
myQueueTest/myqueuetest/Queue.java", line 28, character 24> regardingspecifications at File
"../../home/allen/Desktop/workspace/myQueueTest/myqueuetest/Queue.java", line 22, character 38 …
Note: blame is again likely to be with the callee Queue, since an invariant has been violated.
![Page 17: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/17.jpg)
Class and System Correctness
So far, we have only done testing!What about formal verification?
1. A class C is (formally) correct if:a. It is formally specified, andb. For every object o and every constructor and public
method M in the class, the Hoare triple
is valid for every argument x.
2. A system is correct if all its classes are correct.
€
{P∧INV} o.M(x) {Q∧INV}
![Page 18: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/18.jpg)
E.g., Correctness of dequeue()
/*@ requires n > 0; ensures \result.equals(\old(H).val) && H == \old(H).next;
@*/public Object dequeue( ) {
Object result = first.val;first = first.next;if (first != null) first.prior = null ; To prove:else last = null;n = n-1; where:return result;
}
€
{P∧INV}dequeue(){Q∧INV}
P ≡ n > 0
Q ≡ \result = \old( first).val∧ first = \old( first).next
INV ≡ n = size()
Note: We again use rules of inference and reason through the code, just like we did with Factorial.
1.2.3.4.5.6.7.
![Page 19: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/19.jpg)
A “loose” correctness proof for dequeue()
1. “Loose” because a. We assume the validity of size(), andb. We omit some details.
2. The assignments in dequeue(), together with ,ensure the validity of :1. Steps 1 and 7 establish \result = \old(first).val2. Steps 2-5 establish first = \old(first).next3. Step 6 and our assumption establish n = size():
a. I.e., n = \old(n) -1b. and size() = \old(size()) -1c. So, n = size(), since \old(n) = \old(size())
€
P∧INV
€
Q∧INV
![Page 20: JML and Class Specifications](https://reader035.fdocuments.us/reader035/viewer/2022062323/5681598c550346895dc6d3ae/html5/thumbnails/20.jpg)
More Observations
1. Formal verification:a. is an enormous task for large
programs.b. only proves that specifications and
code agree.c. only proves partial correctness
(assumes termination).
2. Tools exist for:a. Statically checking certain run-time properties of Java
programs (ESC/Java2)b. formally verifying Ada programs (Spark)
3. Tools are being developed to help with formal verificationof Java programs (Diacron, LOOP)
4. What is the cost/benefit of formal methods???