Skip to content

Commit ea47a09

Browse files
author
davidcok
committed
2 parents 4232b94 + 73a1a0c commit ea47a09

25 files changed

+148
-84
lines changed
382 KB
Binary file not shown.

documentation/OpenJMLUserGuide.pdf

192 KB
Binary file not shown.

examples/SelectionSort.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
public class SelectionSort {
55
/*@
66
assigns arr[*];
7-
ensures \forall int k;0 <= k && k < arr.length-1;arr[k] >= arr[k+1];
7+
ensures \forall int k; 0 <= k && k < arr.length-1; arr[k] >= arr[k+1];
88
@*/
9+
// Sorts the array in-place from maximum down to minimum
910
public static void sort(int /*@ non_null @*/ [] arr) {
1011
//@ ghost final int n = arr.length;
1112

1213
//@ loop_invariant 0 <= i <= n; // Bounds check
13-
/*@ loop_invariant \forall int j; 0 <= j < i; // Sorted up-to i
14-
\forall int k; j < k < n; arr[j] >= arr[k];
15-
@*/
14+
//@ loop_invariant \forall int j; 0 <= j < i; // Sorted up-to i
15+
//@ \forall int k; j < k < n; arr[j] >= arr[k];
1616
//@ loop_assigns i, arr[*];
1717
//@ decreasing n-i; // i goes up
1818
for (int i = 0; i < arr.length; i++) {
@@ -24,7 +24,7 @@ public static void sort(int /*@ non_null @*/ [] arr) {
2424

2525
//@ loop_invariant i < j <= n; // Bounds check
2626
//@ loop_invariant \forall int k; i <= k < j; ub >= arr[k]; // max elem up-to j
27-
//@ loop_invariant i <= l < n; // max index bounds check
27+
//@ loop_invariant i <= l < j; // max index bounds check
2828
//@ loop_invariant ub == arr[l]; // max index corresponds to max elem.
2929
//@ loop_assigns j, l, ub;
3030
//@ decreasing n-j; // j goes up
@@ -36,9 +36,6 @@ public static void sort(int /*@ non_null @*/ [] arr) {
3636
}
3737
// Maximum is at position l
3838

39-
// assert \forall int k; 0 <= k < i; largest <= arr[k];
40-
// assert \forall int k; i <= k < n; largest >= arr[k];
41-
4239
arr[l] = arr[i];
4340
arr[i] = ub;
4441
}

examples/userguide-examples.zip

-3 Bytes
Binary file not shown.

tutorial/Execution.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ title: JML Tutorial - Executing openjml
44

55
## Options and files
66

7-
The `openjml` executable is a modified version of the OpenJDK `javac`
7+
The `openjml` executable is a modified version of the OpenJDK compiler `javac`
88
and is correspondingly a classic command-line tool:
99
* The command-line arguments are a mix of files and options.
1010
* Files are given as absolute file paths
1111
or paths relative to the current working directory
1212
(not relative to the location of `openjml`).
1313
* Options inherited from `javac` are unchanged. They are a mix of single-hyphen and double-hyphen spellings.
1414
* OpenJML-specific options begin with a double hyphen (e.g., `--quiet`) (single hyphens are still accepted for most options).
15-
Options that take a value either (a) have the value follow the option as the next argument or (b)
15+
Options that take a value either: (a) have the value follow the option as the next argument or (b)
1616
(for OpenJML options, but only some Java option) use the syntax `--option=value`.
1717
For some options, the value may be a comma-separated list; if the value contains
1818
whitespace, it must be enclosed in quotes.
@@ -23,7 +23,7 @@ The details of all the options are given in the [OpenJML Users' Guide](../docume
2323
* `--rac`: compile with embedded checks, for runtime-assertion-checking
2424
* `--progress`: emits more information during processing than the default `--normal`
2525

26-
Use `--class-path` or `-cp` just as you would for `javac` to specify the list of folders on which to find files. `openjml` uses a classpath and a sourcepath exactly like `javac` does; in addition `openjml` considers a _specspath_ for finding specification files. For most applications, it is simplest to define a single classpath (using the `-cp` command-line option or the `CLASSPATH` environment variable) giving the jar files and folder roots of package hierarchies for all the class, source and specification files. The details are an advanced topic presented [here](SpecificationFiles).
26+
Use `--class-path` or `-cp` just as you would for `javac` (i.e., with a path argument after a space, such as `-cp '/home/me/project1:/home/me/prjoject2'`) to specify the list of folders on which to find files. `openjml` uses a classpath and a sourcepath exactly like `javac` does; in addition `openjml` also uses a _specspath_ for finding specification files. For most applications, it is simplest to define a single classpath (using the `-cp` command-line option or the `CLASSPATH` environment variable) giving the jar files and folder roots of package hierarchies for all the class, source and specification files. The details are an advanced topic presented [here](SpecificationFiles).
2727

2828
A simple, example command-line is `openjml --esc --progress A.java` .
2929

tutorial/FrameConditions.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ in the pre-state, that is, the state at the beginning of the method's execution.
2020
`counter1` without the `\old` designator means the value of `counter1` in the
2121
post-state, the state after the method has completed.
2222

23-
Also, why the comparison to `Integer.MAX_VALUE`? That is to avoid warnings about arithmetic overflow. We'll get to that topic [later](ArithmeticModes).
23+
Also, why the comparison to `Integer.MAX_VALUE` in the preconditions? That is to avoid warnings about arithmetic overflow. We'll get to that topic [later](ArithmeticModes).
2424

2525
Now to the point of this lesson. The two increment methods verify, but
2626
what is happening in the test method?
@@ -36,7 +36,7 @@ that `counter2` is unchanged. One solution would be to add an additional
3636
ensures clause that states that `counter2 == \old(counter2)`. This specification
3737
verifies as correct.
3838

39-
But this is not a practical solution. We can't add to `increment1()`'s specification a clause stating that every visible variable is unchanged.
39+
But adding such postconditions is not a practical solution. We can't add to `increment1()`'s specification a clause stating that every visible variable is unchanged.
4040
Instead we use a *frame condition* whose purpose is to state which memory
4141
locations a method might have modified. There are a variety of names for
4242
the frame clause: traditionally it is `assignable`, but `assigns` and `writes` are also permitted.
@@ -70,12 +70,12 @@ program state outside of the method.
7070
* The formal arguments of the method are in scope for the frame condition,
7171
just like for the `requires` and `ensures` clauses. The formal arguments
7272
themselves cannot be changed by a method, but if they are references to objects,
73-
their fields might be written to by a method. So a method `m(MyType q)`
73+
then the fields of those objects might be written to by the method. So a method `m(MyType q)`
7474
might have a frame condition `assigns q.f;` if `f` is a field of `MyType`
7575
that is written to in the body of `m`.
7676
* If a method has no external effects other than its return value, you can specify a frame condition `assigns \nothing;`
7777
* `q.*` for an expression `q` means all fields of q
78-
* `a[i]` for expression `a` and `i` means that particular array element
78+
* `a[i]` for expressions `a` and `i` means the particular array element `a[i]` (where the values of `a` and `i` are interpreted in the method's pre-state)
7979
* `a[*]` for array expression `a` means all elements of that array
8080
* `a[i..j]` for expressions `a`, `i`, and `j` means the stated range of array elements, from `i` to `j` inclusive.
8181

@@ -88,7 +88,7 @@ public void m() { ... }
8888
```
8989
though there are a few other details to purity --- see the [lesson on pure](MethodsInSpecifications).
9090

91-
There are two other points to know about frame conditions. First, where a frame condition clause includes expressions, such as the indices of array expressions, those expressions are evaluated in the pre-state, not the post-state.
91+
There are two other points to know about frame conditions. First, where a frame condition clause includes expressions, such as the indices of array expressions, those expressions are evaluated in the pre-state, not the post-state. This allows callers of the method to understand the potential side-effects of the method before calling it.
9292

9393
Second, a frame condition is a method specification clause like `requires` and `ensures`. A method specification may contain more than one such clause.
9494
However, note that each clause is considered individually. That is, each clause

tutorial/InitiallyConstraint.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
title: JML Tutorial - Minimizing replicated specifications (initially, constraint, invariant clauses)
33
---
44

5-
Sometimes it is the case that certain properties must hold at the end of every constructor or every method.
6-
Then the specifications for each method or constructor have to repeat the same specification clause.
7-
There is a danger that (a) such a clause will be forgotten for some constructor or method and (b) if the clause needs to be modified, it will not be correctly changed in every place it appears.
5+
Sometimes certain properties must hold at the end of every constructor or every method.
6+
Then the specifications for each method or constructor would have to repeat the same specification clause in every constructor or method's specification.
7+
However, there is a danger that: (a) such a clause will be forgotten for some constructor or method and (b) if the clause needs to be modified, it will not be correctly changed in every place it appears.
88

9-
So JML has a few features to coalesce such replicated clauses. These clauses are part of the _class_ declaration, but apply to every method or constructor as described below.
9+
So JML has a few features to coalesce such replicated clauses. These clauses are part of the _class_ declaration, but apply to every method or constructor in the class (or interface) as described below.
1010

1111
## Initially clauses
1212

13-
An `initially` clause at the class level is equivalent to a corresponding `ensures` clause at the end of every constructor, including an unwritten default constructor. For example, suppose we are constructing rectangles and want to ensure that, at least upon construction, every such rectangle has a length larger than its width, which is larger than 0. We might write
13+
An `initially` clause at the class level is equivalent to a corresponding `ensures` clause at the end of every constructor, including any unwritten default constructor. For example, suppose we are constructing rectangles and want to ensure that, at least upon construction, every such rectangle has a length larger than its width, which is larger than 0. We might write
1414
```
1515
{% include_relative T_initially1.java %}
1616
```
@@ -20,7 +20,7 @@ This yields
2020
```
2121
This verification failure is understandable. We did not specify a precondition that `0 < width < length`, so the stated initially clause cannot be fulfilled.
2222
But why is there no failure for the second constructor? The second constructor calls `this(0,0)`, using the first constructor. Because it is calling that
23-
constructor, it only uses that constructor's specifications in reasoning about its own implementation. So the second constructor sees
23+
constructor, it only uses that constructor's specifications in reasoning about its own implementation. So the call of the first constructor by the second constructor sees
2424
```
2525
assume \let width = 0 && length = 0 in (this.width == width && this.length == length)
2626
assume 0 < this.width < this.length
@@ -32,13 +32,13 @@ If we insert a precondition to fix the verification of the first constructor, we
3232
```
3333
{% include_relative T_initially2.java %}
3434
```
35-
which yeilds
35+
which yields:
3636
```
3737
{% include_relative T_initially2.out %}
3838
```
3939
Now the first constructor passes verification, but the second one does not. The reason is obvious:
40-
the size we have given for a default rectangle (0 by 0) does not satisfy our desired `initially` postcondition.
41-
We'll have a to pick a different size -- 1x2 perhaps.
40+
the size we have given for a default rectangle (0 by 0) does not satisfy our desired `initially` postcondition, which was enforced by the new precondition on the first constructor.
41+
To fix this failure, we would have a to pick different sizes -- 1x2 perhaps.
4242

4343
## Constraint clauses
4444

tutorial/Introduction.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
title: JML Tutorial - What is Deductive Verification?
33
---
44

5-
We know you are eager to just try out some code, but here is a quick set of bullet points to be sure you understand where this tutorial is headed:
6-
* JML is a language for writing specifications for Java programs
7-
* OpenJML is tool for checking that the Java implementation of the program is consistent with the JML specifications
8-
* This checking can either be done statically (without running the program) -- called Deductive Verification - DV or ESC (Extended static checking)
9-
* or it can be done by running test cases through an instrumented program (RAC - runtime-assertion-checking)
5+
We know you are eager to just try out some code, but here is a quick set of points to be sure you understand where this tutorial is headed:
6+
* JML is a language for writing specifications of the behavior of Java programs.
7+
* OpenJML is tool for checking that the Java implementation of the program is consistent with its JML specifications.
8+
* This checking can either be done:
9+
* statically (without running the program) -- called Deductive Verification, - DV or ESC (Extended Static Checking), or
10+
* dynamically by running test cases through an instrumented program - RAC (Runtime Assertion Checking).
1011

1112
The tutorial is mostly focussed on DV/ESC (though there are lessons on RAC as well):
1213
* The DV approach is akin to logically symbolically executing a method for every possible legal set of inputs (every possible pre-state)

tutorial/MethodCalls.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
title: JML Tutorial - Method Calls
33
---
44

5-
We have seen how to verify methods that have pre- and postconditions to describe
5+
We have seen how to verify method implementations that have
6+
pre- and postconditions describing
67
the behavior of method bodies that contain if statements and assignments.
78
Now let's progress to method calls.
89

910
The key point to remember is that verification in JML (and other similar
1011
deductive verification languages and tools) is *modular by method*.
1112
That is, each method is verified on its own; only when all methods are
12-
verified with a consistent set of specifications across all of them can the program as a whole be
13+
verified with a consistent set of specifications
14+
across all of them can the program as a whole be
1315
considered verified.
1416

1517
Consider two methods, a caller and a callee, as shown in this diagram.
@@ -30,7 +32,7 @@ pre- and post-conditions. We know that the callee's postconditions will be true
3032
* must prove (assert) that the callee's preconditions hold
3133
* and then it may assume that the callee's postconditions will hold
3234

33-
As long as we keep the callee's specifications the same, we can verify the callee and the caller independently.
35+
As long as we keep the callee's specifications the same, we can verify the callee and the caller independently. (Thus the callee's specification is a summary of its behavior and is not affected by the callee's implementation details.)
3436

3537
It is easy to see that this process works for verifying the methods in a program that do not call anything, to those methods that just call those leaves, all the way up to the top-level methods of the program. It can also be demonstrated that this process is sound when there are recursive calls, as long as it can
3638
be proved that the program terminates.
@@ -51,7 +53,7 @@ the `--progress` option, so we receive quite a bit more output.
5153
Looking at this piece by piece:
5254
* The method `lessThanDouble` requires positive inputs with the first argument
5355
larger than the second. It returns true if the first argument is less than double the second. The method proves without a problem.
54-
The output about `lessThanDouble` is near the end of the listing.
56+
The output about `lessThanDouble` is near the end of the verification listing above.
5557
* The default constructor `T_CallerCallee()` also verifies without problem.
5658
* The method `caller1` calls `lessThanDouble` for two test cases and checks
5759
that the result is what is expected. This method also verifies.

0 commit comments

Comments
 (0)