Title: Model-Checking JML Specifications with Bogor
1Model-Checking JML Specifications with Bogor
SAnToS Laboratory, Kansas State University, USA
CASSIS 2004, Marseille, France
http//bogor.projects.cis.ksu.edu
Robby
Edwin Rodríguez
http//spex.projects.cis.ksu.edu
http//jmleclipse.projects.cis.ksu.edu
Matthew B. Dwyer
John Hatcliff
http//bandera.projects.cis.ksu.edu
Support
Boeing Honeywell Technology Center IBM Intel
US Army Research Office (ARO) US National Science
Foundation (NSF) US Department of Defense
Advanced Research Projects Agency (DARPA)
Lockheed Martin NASA Langley Rockwell-Collins
ATC Sun Microsystems
2BanderaAn Open Toolset for Model Checking
Concurrent Java Programs
Checker Input
Slicing
Specification
Abstract Interpretation
Bogor
Static Analysis
Checker Output
3SpEx Project Goals
- specification languages should
- have a rich set of primitives for observing
program state - heap-allocated objects, concurrency, etc.
- make it easy to write useful specifications
- support lightweight and deep-semantic
specifications - be checkable using a variety of analysis
techniques - model checking, testing, etc.
- We are investigating several languages
- JML (current focus), OCL, AAL, etc.
4JML Reasoning Tools and Technologies
Tool(technology) Automaton Usability JML Coverage Behavior Coverage Scalability
LOOP fair (straight line code), poor (otherwise) very high complete (for sequential) poor
ESC/Java good (annotations usually needed) low high (for sequential), moderate (otherwise) excellent (modular treatment of methods)
ESC/Java2 good (annotations usually needed) moderate high (for sequential), moderate (otherwise) excellent (modular treatment of methods)
JMLC excellent moderate low (determined by test harness) excellent
Bogor excellent very high moderate (determined by test harness) good (for unit-level reasoning)
other tools such as JACK,
5JML Reasoning Tools and Technologies
Model Checking/Testing
Theorem Proving
m()
m() assume pre-conditions
prove post-conditions
checking that specifications are satisfied for
particular traces generated by the environment
(test harness)
manipulate formulas
6Bogor
Questions
- What is it?
- Why is it useful?
- What about its existing algorithms suggests that
it might be good for checking JML?
7Bogor (Buitenzorg)
8Bogor Software Model Checking Framework
9Bogor Direct support for OO software
Extensive support for checking concurrent OO
software
Software targeted algorithms
Direct support for
- unbounded dynamic creation of threads and objects
- automatic memory management (garbage collection)
- virtual methods,
- , exceptions, etc.
- supports virtually all of Java
- thread heap symmetry
- compact state representation
- partial order reduction techniques driven by
- object escape analysis
- locking disciplines
10Bogor Eclipse-based Tool Components
11Domain-Specific Model-Checking Bogor Customized
To Cadena
Real-time Scheduling
Quasi-cyclic Search
Partial State Representation
12Bogor Customized To Bandera
Partial Order Reduction
Depth-first Search
Symm. Reduc. Compression
13Bogors Heap Representation
Key Points
State
explicit heap representation
after each transition, a topological sort gives
heap objects a canonical order
transition may create new objects, garbage, etc.
garbage is eliminated
precise heap model
precise alias information
have access to all visited states (but,
efficiently stored using collapse compression)
14Bogors Heap Representation Enables JML Specs
Check
Key Points
State
many JML features are easy to support in Bogor
precise heap model (c.f., \reach)
transition may create new objects, garbage, etc.
precise alias information (c.f., \modifies)
can easily compare objects in methods
pre/post-states (c.f., \old)
15JML Language Coverage
large language coverage
16Doug Leas LinkedQueue Example
public class LinkedNode public Object value
public LinkedNode next public
LinkedNode(Object x) value x
public class LinkedQueue protected final
Object putLock protected LinkedNode head
protected LinkedNode last head protected int
waitingForTake 0 public LinkedQueue()
putLock new Object() head new
LinkedNode(null) public boolean isEmpty()
synchronized (head) return
head.next null public void
put(Object x) if (x null) throw
new IllegalArgumentException() insert(x)
protected synchronized Object extract()
synchronized (head) Object x null
LinkedNode first head.next if (first !
null) x first.value first.value
null head first return x
protected void insert(Object x)
synchronized (putLock) LinkedNode p new
LinkedNode(x) synchronized (last)
last.next p last p if
(waitingForTake gt 0) putLock.notify()
return public Object take() Object x
extract() if (x ! null) return x else
allows a high degree of concurrency
17Doug Leas LinkedQueue Example
head
LQ
LN
last
putLock
A state with two threads and a LinkedQueue object
18Doug Leas LinkedQueue Example
head
LQ
LN
last
putLock
The red thread creates a new object
19Doug Leas LinkedQueue Example
put()
head
LQ
LN
last
putLock
and invokes put(), which invokes insert()
20Doug Leas LinkedQueue Example
put()
head
LQ
LN
last
putLock
insert() acquires the lock on putLock
21Doug Leas LinkedQueue Example
p
put()
value
head
LQ
LN
LN
last
putLock
and creates a new LinkedNode
22Doug Leas LinkedQueue Example
p
put()
value
head
LQ
LN
LN
last
putLock
then it locks the LinkedNode pointed by last
23Doug Leas LinkedQueue Example
p
put()
value
head
next
LQ
LN
LN
last
putLock
and assigns new LinkedNode to last.next
24Doug Leas LinkedQueue Example
p
put()
value
head
next
LQ
LN
LN
putLock
last
last is moved to point to the new LinkedNode
25Doug Leas LinkedQueue Example
p
put()
value
head
next
LQ
LN
LN
putLock
last
the lock on heads LinkedNode is released
26Doug Leas LinkedQueue Example
put()
value
head
next
LQ
LN
LN
putLock
last
returning from insert(), the local p is now out
of scope
27Doug Leas LinkedQueue Example
put()
value
head
next
LQ
LN
LN
putLock
last
and the lock on putLocks object is released
28Doug Leas LinkedQueue Example
value
head
next
LQ
LN
LN
putLock
last
The red thread finishes executing the put() method
29Doug Leas LinkedQueue Example
value
head
next
LQ
LN
LN
putLock
last
and it removes the reference to the new object,
done!
30Doug Leas LinkedQueue Example
value
value
head
next
next
LQ
LN
LN
LN
putLock
last
another object is added
31Doug Leas LinkedQueue Example
value
value
head
next
next
LQ
LN
LN
LN
take()
putLock
last
The blue thread invokes take(), which invokes
extract()
32Doug Leas LinkedQueue Example
value
value
head
next
next
LQ
LN
LN
LN
take()
putLock
last
the LinkedQueue is locked
33Doug Leas LinkedQueue Example
value
value
head
next
next
LQ
LN
LN
LN
take()
putLock
last
the heads LinkedNode is also locked
34Doug Leas LinkedQueue Example
value
value
head
next
next
LQ
LN
LN
LN
take()
putLock
last
first
head.next is assigned to the local first
35Doug Leas LinkedQueue Example
x
value
value
head
next
next
LQ
LN
LN
LN
take()
putLock
last
first
first.value is assigned to the local x
36Doug Leas LinkedQueue Example
x
value
head
next
next
LQ
LN
LN
LN
take()
putLock
last
first
first.value is assigned null
37Doug Leas LinkedQueue Example
x
head
value
next
next
LQ
LN
LN
LN
take()
putLock
last
first
head is moved to the next LinkedNode
38Doug Leas LinkedQueue Example
x
head
value
next
LQ
LN
LN
take()
putLock
last
the LinkedNode is GCed (after its lock released)
39Doug Leas LinkedQueue Example
value
head
next
LQ
LN
LN
putLock
last
x
the state after take() is finished
40Assessments LinkedQueue
- put() and take()
- can be done concurrently
- if the size of the LinkedQueue is greater than 0
- they use different locks to protect object
accesses - put() synchronizes on putLock and last
- take() synchronizes on the LinkedQueue object and
head - are mutually exclusive
- if the size is 0
- synchronize on the same LinkedNode
- head last
- reasoning about them becomes very complex
41JML Concurrency Issues
- Pre-/post-conditions
- check points in a concurrent setting
- Functional and synchronization aspects
- difficulty when specifying methods
- Model checking post-conditions with \old()
42LinkedQueue Example (JML)
/_at_ behavior _at_ requires x ! null _at_
ensures true _at_ also behavior _at_ requires
x null _at_ signals (Exception e) e
instanceof IllegalArgumentException _at_/
public void put(Object x) if (x null)
throw new IllegalArgumentException()
insert(x) protected synchronized Object
extract() synchronized (head)
return refactoredExtract() /_at_
behavior _at_ assignable head,
head.next.value _at_ ensures \result null
(\exists LinkedNode n _at_
\old(\reach(head)).has(n) _at_
n.value \result
_at_
!(\reach(head).has(n))) _at_/ protected
Object refactoredExtract() Object x
null LinkedNode first head.next if
(first ! null) x first.value
first.value null head first
return x /_at_ behavior _at_ requires x
! null _at_ ensures last.value x
\fresh(last) _at_/ protected void
insert(Object x) synchronized (putLock)
LinkedNode p new LinkedNode(x)
synchronized (last) refactoredInsert(p) if
(waitingForTake gt 0) putLock.notify()
return
public class LinkedNode public Object value
public LinkedNode next /_at_ behavior _at_
ensures value x _at_/ public
LinkedNode(Object x) value x
public class LinkedQueue protected final
/_at_ non_null _at_/ Object putLock protected /_at_
non_null _at_/ LinkedNode head protected /_at_
non_null _at_/ LinkedNode last head protected
int waitingForTake 0 //_at_ instance invariant
waitingForTake gt 0 //_at_ instance invariant
\reach(head).has(last) /_at_ behavior _at_
assignable head, last, putLock, waitingForTake
_at_ ensures \fresh(head, putLock) head.next
null _at_/ public LinkedQueue()
putLock new Object() head new
LinkedNode(null) /_at_ behavior _at_
ensures \result ltgt head.next null _at_/
public boolean isEmpty() synchronized
(head) return head.next null
/_at_ behavior _at_ requires n ! null
_at_ assignable last, last.next _at_/
protected void refactoredInsert(LinkedNode n)
last.next n last n
43LinkedQueue Example (JML)
/_at_ behavior _at_ requires x ! null _at_
ensures true _at_ also behavior _at_ requires
x null _at_ signals (Exception e) e
instanceof IllegalArgumentException _at_/
public void put(Object x) if (x null)
throw new IllegalArgumentException()
insert(x) protected synchronized Object
extract() synchronized (head)
return refactoredExtract() /_at_
behavior _at_ assignable head,
head.next.value _at_ ensures \result null
(\exists LinkedNode n _at_
\old(\reach(head)).has(n) _at_
n.value \result
_at_
!(\reach(head).has(n))) _at_/ protected
Object refactoredExtract() Object x
null LinkedNode first head.next if
(first ! null) x first.value
first.value null head first
return x /_at_ behavior _at_ requires x
! null _at_ ensures last.value x
\fresh(last) _at_/ protected void
insert(Object x) synchronized (putLock)
LinkedNode p new LinkedNode(x)
synchronized (last) refactoredInsert(p) if
(waitingForTake gt 0) putLock.notify()
return
public class LinkedNode public Object value
public LinkedNode next /_at_ behavior _at_
ensures value x _at_/ public
LinkedNode(Object x) value x
public class LinkedQueue protected final
/_at_ non_null _at_/ Object putLock protected /_at_
non_null _at_/ LinkedNode head protected /_at_
non_null _at_/ LinkedNode last head protected
int waitingForTake 0 //_at_ instance invariant
waitingForTake gt 0 //_at_ instance invariant
\reach(head).has(last) /_at_ behavior _at_
assignable head, last, putLock, waitingForTake
_at_ ensures \fresh(head, putLock) head.next
null _at_/ public LinkedQueue()
putLock new Object() head new
LinkedNode(null) /_at_ behavior _at_
ensures \result ltgt head.next null _at_/
public boolean isEmpty() synchronized
(head) return head.next null
/_at_ behavior _at_ requires n ! null
_at_ assignable last, last.next _at_/
protected void refactoredInsert(LinkedNode n)
last.next n last n
public class LinkedQueue protected final /_at_
non_null _at_/ Object putLock protected /_at_
non_null _at_/ LinkedNode head protected /_at_
non_null _at_/ LinkedNode last head protected
int waitingForTake 0 //_at_ instance invariant
waitingForTake gt 0 //_at_ instance invariant
\reach(head).has(last)
44LinkedQueue Example (JML)
/_at_ behavior _at_ requires x ! null _at_
ensures true _at_ also behavior _at_ requires
x null _at_ signals (Exception e) e
instanceof IllegalArgumentException _at_/
public void put(Object x) if (x null)
throw new IllegalArgumentException()
insert(x) protected synchronized Object
extract() synchronized (head)
return refactoredExtract() /_at_
behavior _at_ assignable head,
head.next.value _at_ ensures \result null
(\exists LinkedNode n _at_
\old(\reach(head)).has(n) _at_
n.value \result
_at_
!(\reach(head).has(n))) _at_/ protected
Object refactoredExtract() Object x
null LinkedNode first head.next if
(first ! null) x first.value
first.value null head first
return x /_at_ behavior _at_ requires x
! null _at_ ensures last.value x
\fresh(last) _at_/ protected void
insert(Object x) synchronized (putLock)
LinkedNode p new LinkedNode(x)
synchronized (last) refactoredInsert(p) if
(waitingForTake gt 0) putLock.notify()
return
public class LinkedNode public Object value
public LinkedNode next /_at_ behavior _at_
ensures value x _at_/ public
LinkedNode(Object x) value x
public class LinkedQueue protected final
/_at_ non_null _at_/ Object putLock protected /_at_
non_null _at_/ LinkedNode head protected /_at_
non_null _at_/ LinkedNode last head protected
int waitingForTake 0 //_at_ instance invariant
waitingForTake gt 0 //_at_ instance invariant
\reach(head).has(last) /_at_ behavior _at_
assignable head, last, putLock, waitingForTake
_at_ ensures \fresh(head, putLock) head.next
null _at_/ public LinkedQueue()
putLock new Object() head new
LinkedNode(null) /_at_ behavior _at_
ensures \result ltgt head.next null _at_/
public boolean isEmpty() synchronized
(head) return head.next null
/_at_ behavior _at_ requires n ! null
_at_ assignable last, last.next _at_/
protected void refactoredInsert(LinkedNode n)
last.next n last n
/_at_ behavior _at_ assignable head, last,
putLock, waitingForTake _at_ ensures
\fresh(head, putLock) head.next null
_at_/ public LinkedQueue() putLock new
Object() head new LinkedNode(null)
45LinkedQueue Example (JML)
/_at_ behavior _at_ requires x ! null _at_
ensures true _at_ also behavior _at_ requires
x null _at_ signals (Exception e) e
instanceof IllegalArgumentException _at_/
public void put(Object x) if (x null)
throw new IllegalArgumentException()
insert(x) protected synchronized Object
extract() synchronized (head)
return refactoredExtract() /_at_
behavior _at_ assignable head,
head.next.value _at_ ensures \result null
(\exists LinkedNode n _at_
\old(\reach(head)).has(n) _at_
n.value \result
_at_
!(\reach(head).has(n))) _at_/ protected
Object refactoredExtract() Object x
null LinkedNode first head.next if
(first ! null) x first.value
first.value null head first
return x /_at_ behavior _at_ requires x
! null _at_ ensures last.value x
\fresh(last) _at_/ protected void
insert(Object x) synchronized (putLock)
LinkedNode p new LinkedNode(x)
synchronized (last) refactoredInsert(p) if
(waitingForTake gt 0) putLock.notify()
return
public class LinkedNode public Object value
public LinkedNode next /_at_ behavior _at_
ensures value x _at_/ public
LinkedNode(Object x) value x
public class LinkedQueue protected final
/_at_ non_null _at_/ Object putLock protected /_at_
non_null _at_/ LinkedNode head protected /_at_
non_null _at_/ LinkedNode last head protected
int waitingForTake 0 //_at_ instance invariant
waitingForTake gt 0 //_at_ instance invariant
\reach(head).has(last) /_at_ behavior _at_
assignable head, last, putLock, waitingForTake
_at_ ensures \fresh(head, putLock) head.next
null _at_/ public LinkedQueue()
putLock new Object() head new
LinkedNode(null) /_at_ behavior _at_
ensures \result ltgt head.next null _at_/
public boolean isEmpty() synchronized
(head) return head.next null
/_at_ behavior _at_ requires n ! null
_at_ assignable last, last.next _at_/
protected void refactoredInsert(LinkedNode n)
last.next n last n
/_at_ behavior _at_ ensures \result ltgt head.next
null _at_/ public boolean isEmpty()
synchronized (head) return head.next
null
46Pre/Post-Conditions
Figure 4.3, A Runtime Assertion Checker for the
Java Modeling Language, Y. Cheon
47Pre/Post-Conditions
Figure 4.3, A Runtime Assertion Checker for the
Java Modeling Language, Y. Cheon
48Pre/Post-Conditions
Figure 4.3, A Runtime Assertion Checker for the
Java Modeling Language, Y. Cheon
49Pre/Post-Conditions
Figure 4.3, A Runtime Assertion Checker for the
Java Modeling Language, Y. Cheon
50Pre/Post-Conditions
/_at_ behavior _at_ ensures \result ltgt head.next
null _at_/ public boolean isEmpty()
synchronized (head) return head.next
null
public boolean isEmpty() boolean
racresult racresult origisEmpty()
checkPostisEmptyLinkedQueue(racresult)
return racresult
51Pre/Post-Conditions
/_at_ behavior _at_ ensures \result ltgt head.next
null _at_/ public boolean isEmpty()
synchronized (head) return head.next
null
public boolean isEmpty() boolean
racresult racresult origisEmpty()
checkPostisEmptyLinkedQueue(racresult)
return racresult
52Pre/Post-Conditions
/_at_ behavior _at_ ensures \result ltgt head.next
null _at_/ public boolean isEmpty()
synchronized (head) return head.next
null
public boolean isEmpty() boolean
racresult racresult origisEmpty()
checkPostisEmptyLinkedQueue(racresult)
return racresult
53Assessments Pre/Post-conditions
- granularity of execution/checking steps must be
controlled - easy to do in a model checker
- using similar construct such as Promelas atomic
- needs to modify JVM for testing
- the scheduler must prevent context-switching when
evaluating code from specifications
54JML Concurrency Issues
- Pre-/post-conditions
- check points in a concurrent setting
- Functional and synchronization aspects
- difficulty when specifying methods
- Model checking post-conditions with \old()
55Functional andSynchronization Aspects
/_at_ behavior _at_ requires x ! null _at_
ensures true _at_ also behavior _at_ requires
x null _at_ signals (Exception e) e
instanceof IllegalArgumentException _at_/
public void put(Object x) if (x null)
throw new IllegalArgumentException()
insert(x) protected synchronized Object
extract() synchronized (head)
return refactoredExtract() /_at_
behavior _at_ assignable head,
head.next.value _at_ ensures \result null
(\exists LinkedNode n _at_
\old(\reach(head)).has(n) _at_
n.value \result
_at_
!(\reach(head).has(n))) _at_/ protected
Object refactoredExtract() Object x
null LinkedNode first head.next if
(first ! null) x first.value
first.value null head first
return x /_at_ behavior _at_ requires x
! null _at_ ensures last.value x
\fresh(last) _at_/ protected void
insert(Object x) synchronized (putLock)
LinkedNode p new LinkedNode(x)
synchronized (last) refactoredInsert(p) if
(waitingForTake gt 0) putLock.notify()
return
public class LinkedNode public Object value
public LinkedNode next /_at_ behavior _at_
ensures value x _at_/ public
LinkedNode(Object x) value x
public class LinkedQueue protected final
/_at_ non_null _at_/ Object putLock protected /_at_
non_null _at_/ LinkedNode head protected /_at_
non_null _at_/ LinkedNode last head protected
int waitingForTake 0 //_at_ instance invariant
waitingForTake gt 0 //_at_ instance invariant
\reach(head).has(last) /_at_ behavior _at_
assignable head, last, putLock, waitingForTake
_at_ ensures \fresh(head, putLock) head.next
null _at_/ public LinkedQueue()
putLock new Object() head new
LinkedNode(null) /_at_ behavior _at_
ensures \result ltgt head.next null _at_/
public boolean isEmpty() synchronized
(head) return head.next null
/_at_ behavior _at_ requires n ! null
_at_ assignable last, last.next _at_/
protected void refactoredInsert(LinkedNode n)
last.next n last n
public Object take() Object x extract()
if (x ! null) return x else // wait /_at_
behavior _at_ assignable head, head.next.value
_at_ ensures \result null _at_
(\exists LinkedNode n _at_
\old(\reach(head)).has(n) _at_
n.value \result _at_
!(\reach(head).has(n))) _at_/ protected
synchronized Object extract() synchronized
(head) Object x null LinkedNode
first head.next if (first ! null)
x first.value first.value null
head first return x
does not work, why?
56Functional andSynchronization Aspects
head
LQ
LN
last
putLock
A state with two threads and a LinkedQueue object
57Functional andSynchronization Aspects
head
LQ
LN
take()
last
putLock
The blue thread invokes take(), which invokes
extract(). Note that the pre-state for take() is
an empty LinkedQueue.
58Functional andSynchronization Aspects
put()
head
LQ
LN
take()
last
putLock
The red thread interleaves and put() an object
59Functional andSynchronization Aspects
value
head
head
next
LQ
LN
LN
LN
take()
putLock
last
The red thread interleaves and put() an object
60Functional andSynchronization Aspects
head
LQ
LN
take()
last
putLock
x
The blue thread successfully take() the object
61Functional andSynchronization Aspects
public Object take() Object x extract()
if (x ! null) return x else // wait /_at_
behavior _at_ assignable head, head.next.value
_at_ ensures \result null _at_
(\exists LinkedNode n _at_
\old(\reach(head)).has(n) _at_
n.value \result _at_
!(\reach(head).has(n))) _at_/ protected
synchronized Object extract() synchronized
(head) Object x null LinkedNode
first head.next if (first ! null)
x first.value first.value null
head first return x
head
LQ
LN
take()
last
putLock
x
functional property
but the post-condition is violated since the
pre-state is an empty LinkedQueue!
62Functional and Synchronization Aspects
/_at_ behavior _at_ requires x ! null _at_
ensures true _at_ also behavior _at_ requires x
null _at_ signals (Exception e) e instanceof
IllegalArgumentException _at_/ public void
put(Object x) if (x null) throw new
IllegalArgumentException() insert(x) protec
ted synchronized Object extract()
synchronized (head) return
refactoredExtract() /_at_ behavior _at_
assignable head, head.next.value _at_ ensures
\result null (\exists LinkedNode n _at_
\old(\reach(head)).has(n
) _at_ n.value
\result _at_
!(\reach(head).has(n))) _at_/ protected Object
refactoredExtract() Object x null
LinkedNode first head.next if (first !
null) x first.value first.value
null head first return x /_at_
behavior _at_ requires x ! null _at_ ensures
last.value x \fresh(last) _at_/ protected
void insert(Object x) synchronized (putLock)
LinkedNode p new LinkedNode(x)
synchronized (last) refactoredInsert(p) if
(waitingForTake gt 0) putLock.notify()
return
protected synchronized Object extract()
synchronized (head) return
refactoredExtract() /_at_ behavior _at_
assignable head, head.next.value _at_ ensures
\result null _at_ (\exists
LinkedNode n _at_
\old(\reach(head)).has(n) _at_
n.value \result _at_
!(\reach(head).has(n))) _at_/ protected Object
refactoredExtract() Object x null
LinkedNode first head.next if (first !
null) x first.value first.value
null head first return x
public class LinkedNode public Object value
public LinkedNode next /_at_ behavior _at_
ensures value x _at_/ public
LinkedNode(Object x) value x
public class LinkedQueue protected final
/_at_ non_null _at_/ Object putLock protected /_at_
non_null _at_/ LinkedNode head protected /_at_
non_null _at_/ LinkedNode last head protected
int waitingForTake 0 //_at_ instance invariant
waitingForTake gt 0 //_at_ instance invariant
\reach(head).has(last) /_at_ behavior _at_
assignable head, last, putLock, waitingForTake
_at_ ensures \fresh(head, putLock) head.next
null _at_/ public LinkedQueue()
putLock new Object() head new
LinkedNode(null) /_at_ behavior _at_
ensures \result ltgt head.next null _at_/
public boolean isEmpty() synchronized
(head) return head.next null
/_at_ behavior _at_ requires n ! null
_at_ assignable last, last.next _at_/
protected void refactoredInsert(LinkedNode n)
last.next n last n
63Assessments Functional and Synchronization
Aspects
- when specifying properties of concurrent programs
- separate functional properties from
synchronization aspects - e.g., region of code after lock acquires
- if not, we often end up with weaker properties
- a tool support for checking specifications is
valuable for debugging specifications - model checking is good for catching subtle issues
in concurrent programs or their properties
64JML Concurrency Issues
- Pre-/post-conditions
- check points in a concurrent setting
- Functional and synchronization aspects
- difficulty when specifying methods
- Model checking post-conditions with \old()
65Post-conditions with \old
m()
Backtracking can cause MC to miss some errors
66Post-conditions with \old
Backtracking can cause MC to miss some errors
class Race extends Thread static int x
public void run() loc1 x 0 loc2
foo() /_at_ ensures _at_ \old(x) 0
_at_/ void foo() loc3 x 1 loc4
return
67Post-conditions with \old
/_at_ behavior _at_ ensures \old(e)
_at_/ public void foo()
public void foo() oldrac e
68Post-conditions with \old
/_at_ behavior _at_ ensures \old(e)
_at_/ public void foo()
public void foo() int tmp
Bogor.collapseState(e)
69Post-conditions with \old
/_at_ behavior _at_ ensures \old(e)
_at_/ public void foo()
public void foo() int tmp
Bogor.collapseState(e)
70Post-conditions with \old
more optimizations are possible
71Assessments Post-conditions with \old
- Backtracking can cause a model checker to miss
some errors when checking post-conditions with
\old - Needs to distinguish pre-states to avoid
backtracking too early - uses heap symmetry to reduce the number of
distinguishable (observationally inequivalent)
pre-states - uses collapse compression to reduce memory
consumptions for encoding the pre-states - can be optimized further by using a static
analysis to detect relevant heap objects
(analogous to slicing)
72Preliminary Results
w/ JML
w/o JML
Test Platform JDK 1.4.1 (32-bit mode) on a 2 GHz
Opteron with maximum heap of 1 GB running Linux
(64-bit mode)
73Bogors Reduction Algorithms Enables Checking
JML Specs
w/ POR
w/o POR
w/ JML
w/o JML
w/ JML
w/o JML
74JMLEclipse
jmlc
other tool
JML well-formedness checker
75JMLEclipse
JML well-formedness checking
JML syntax highlighting
76Conclusion
- There have been many tools for checking JML
specifications - Bogor flexible model checking framework can be
used to check strong specifications - Complete control over the model checker
representations and algorithms - hard to do it with Spin, but it can be done in
JPF - Highly-automated for unit-sized concurrent Java
programs - requires effective reductions to help curb
specification checking overhead - complements other JML checking methods
- checking a different class of properties
- Issues in JML support for concurrency
- Pre-/post-conditions
- check points in a concurrent setting
- Functional and synchronization aspects
- difficulty when specifying methods
- Checking \old() using model checking
77Future Work
- propose specifications for concurrencyin JML (w/
Cormac Flanagan) - thread-locality
- method-locality
- lock-protected
- pre-/post-conditions on code regions
- atomicity, etc.
- JMLEclipse as an open ended JML plugin for
Eclipse - other specification formalisms
78Bogor Tutorial at ETAPS 2004
- Barcelona, Spain
- April 3, half-day, afternoon
- Topics
- Adapting Bogor to a particular domain
- Extending the Bogor modeling language
- add new abstract data types
- add new abstract operations
- Extending the Bogor model checking algorithms
79For More Information
SAnToS Laboratory, Kansas State
University http//www.cis.ksu.edu/santos
Bogor Project
http//bogor.projects.cis.ksu.edu
SpEx Project
http//spex.projects.cis.ksu.edu
JMLEclipse Project
http//jmleclipse.projects.cis.ksu.edu
Bandera Project
http//bandera.projects.cis.ksu.edu