JML: Expressive, Modular Reasoning
for Java
Gary T. LeavensIowa State University
Support from US National Science FoundationStanford University, March 5, 2007
jmlspecs.org www.cs.iastate.edu/~leavens
Java Modeling Language—JML
Formal specification language for Java Functional behavior Sequential
Goals: Practical, effective for detailed designs Existing code Wide range of tools
Hoare-style Method pre- and postconditions Type invariants
public class Animal implements Gendered {protected /*@ spec_public @*/ int age = 0;
/*@ requires 0 < yrs; @ ensures age == \old(age + yrs); @*/public void older(final int yrs) { age = age + yrs; }
/* … */
}
Example JML Specification
field specification
method behavior specification
Behavioral Interface Specification
JML Specification
Java Code
Syntactic Interface
Functional Behavior
Behavioral Interface Specification
/*@ requires 0 < yrs; @ ensures age == \old(age + yrs); @*/public void older(final int yrs);
public void older(final int yrs) { age = age + yrs; }
public void older(final int yrs);
requires yrs > 0;ensures age == \old(age) + yrs;
Like … But for Java and…
VDM, but OO features
Eiffel, but Features for formal verification
Spec#, but Different invariant methodology More features for formal verification
Research Community
23 groups, worldwide Open Join us
Over 125 papers
See jmlspecs.org for details
Many tools, One Language
public class Animal implements Gendered { // ... protected /*@ spec_public @*/ int age = 0; /*@ requires 0 <= a && a <= 150; @ ensures age == a; @ also @ requires a < 0; @ ensures age == \old(age); @*/ public void setAge(final int a) { if (0 <= a) { age = a; } }}
ESC/Java2
Warnings
Daikon
Data trace file
JML Annotated Java
JACK, Jive, Krakatoa, KeY, LOOP
Correctness proofClass file
jmlc
Unit tests
jmlunit
jmldoc
Web pages
Bogor
Model checkingXVP
Problems for this Talk
Modular Specification, Verification Recording detailed designs Specifying subtypes Verification with OO features
Problem 1:Recording Detailed Designs Precise, sequential behavior Hide details
Approach Model fields Assertions
Model Fields, Ensures
public interface Gendered {
//@ model instance String gender;
//@ ensures \result == gender.equals(“female”);/*@ pure @*/ boolean isFemale();
}
Represents Clauses
public class Animal implements Gendered {
protected boolean gen; //@ in gender;
/*@ protected represents gender @ <- (gen ? “female” : “male”); @*/
// ...
Use of Model Fields
public class Animal implements Gendered {
protected boolean gen; //@ in gender;
/*@ protected represents gender @ <- (gen ? “female” : “male”); @*/
public /*@ pure @*/ boolean isFemale() { return gen; }
// ...
Correctness with Model Fields
gender: “female” true
gen: true true
represents
isFemale’scode
isFemale’sspecification
==
Requires Clauses
public class Animal implements Gendered {
protected boolean gen; //@ in gender;
/*@ protected represents gender @ <- (gen ? “female” : “male”); @*/
//@ requires g.equals(“female”)||g.equals(“male”);//@ ensures gender.equals(g);public Animal(final String g) { gen = g.equals(“female”); }
Model of Method Specifications
public interface T {//@ requires pre;//@ ensures post;void m();
}
T ⊳ (pre, post)
Model of Method Specifications
outputpost-state
input pre-state
pre
post
m()
spec_public Shorthand
Instead of:
//@ public model int age;protected int _age = 0; //@ in age;//@ protected represents age <-
_age;
Write:
protected /*@ spec_public @*/ int age = 0;
Specification Cases, ‘also’
public class Animal implements Gendered {protected /*@ spec_public @*/ int age = 0;
/*@ requires 0 <= a && a <= 150; @ ensures age == a; @ also @ requires a < 0; @ ensures age == \old(age); @*/public void setAge(final int a) { if (0 <= a) { age = a; } }
requires 0 <= a && a <= 150;ensures age == a;
alsorequires a < 0;ensures age == \old(age);
means
requires (0 <= a && a <= 150) || a < 0 ; ensures (\old(0 <= a && a <= 150) ==> age == a)
&& (\old(a < 0) ==> age == \old(age)) ;
Join of Specification Cases
Join of Specification Cases
pre′
post && post′
pre && pre′
pre
post
Join of Specification Cases, ⊔S
If T′ ⊳ (pre′, post′ ), T ⊳ (pre, post ), S ≤ T′, S ≤ T,
then (pre′, post′ ) ⊔S (pre, post )
= (p, q)where p = pre′ || pre
and q = (\old(pre′ ) ==> post′ ) && (\old(pre) ==> post )and S ⊳ (p, q)
Type Specifications:Invariantsimport java.util.*;
public class Patient extends Animal {
//@ public invariant 0 <= age && age <= 150;
protected /*@ spec_public @*/ List log;
/*@ public invariant (\forall int i; @ 0 <= i && i < log.size(); @ log.get(i) instanceof String); @*/
// …
Invariants
Hold in visible states Method pre- & post-, Constructor post-states
Obeyed by subtypes
Invariants: Obeyed by Subtypes Not a Sugar [LW94]
Animal
Patient
Tortoiseinvariant 0 <=
age && age <= 150;
FemalePatient
Initially
public class Patient extends Animal { // ...
protected /*@ spec_public @*/ List log;
//@ public initially log.size() == 0;
True in constructor post-states Basis for datatype induction Not a sugar
History Constraints [LW94]
public class Patient extends Animal { // ...
/*@ public constraint @ \old(log.size()) <= log.size();
@ public constraint @ (\forall int i; @ 0 <= i && i < \old(log.size()); @ log.get(i).equals(\old(log.get(i))));
@*/
History Constraints
Relate pre-states and post-states Inductive step for datatype induction Not a sugar
Problem 2: Specifying Subtypes Avoid repetition (Force behavioral subtyping)
Approach Specification Inheritance
Fields, type specifications Method specification cases
Declared in T (without inheritance):added_invT invariantadded_hcT history constraintadded_initT initially predicate
m’s specification
Other Notations
supers(T ) = {U | T U }
methods(T ) = { m | m declared in TT }
T’s Added Specifications
added_specTm
Methods: for all m methods(supers(T))
= ⊔T { | Usupers(T) }
Invariant:
ext_invT = ⋀ { added_invU | Usupers(T) } History constraint:
ext_hcT = ⋀ { added_hcU | Usupers(T) } Initially:
ext_initT = ⋀ { added_initU | Usupers(T) }
Specification Inheritance’s Meaning:Extended Specification of T
ext_specTm
added_specUm
Invariant Inheritance
public class FemalePatient extends Patient {
//@ public invariant gender.equals(“female”);// …
} Extended invariant:
added_invGendered && added_invAnimal
&& added_invPatient
&& added_invFemalePatient
Invariant Inheritance
public class FemalePatient extends Patient {
//@ public invariant gender.equals(“female”);// …
} Extended invariant:
true && true&& 0 <= age && age <= 150 && (\forall int i; 0 <= i && i < log.size();
log.get(i) instanceof String)&& gender.equals(“female”)
Invariant Inheritance
public class FemalePatient extends Patient {
//@ public invariant gender.equals(“female”);// …
} Extended invariant:
0 <= age && age <= 150 && (\forall int i; 0 <= i && i < log.size();
log.get(i) instanceof String)&& gender.equals(“female”)
Method Specification Inheritance:Supertype’s added_spec
public class Animal implements Gendered { // …
/*@ requires 0 <= a && a <= 150; @ ensures age == a; @ also @ requires a < 0; @ ensures age == \old(age); @*/public void setAge(final int a) { /* … */ }
Method Specification Inheritance:Subtype’s added_specpublic class Patient extends Animal { // …
protected /*@ spec_public @*/ boolean ageDiscount = false; //@ in age;
/*@ also @ requires 0 <= a && a <= 150 || a < 0; @ ensures 65 <= age ==> ageDiscount; @*/public void setAge(final int a) {
super.setAge(a);if (65 <= age) { ageDiscount = true; }
}
= ⊔Patient { ,
}
Method Specification Inheritance:Extended Specification
ext_spec PatientsetAge
added_spec AnimalsetAge
added_spec PatientsetAge
requires 0 <= a && a <= 150; ensures age == a; also requires a < 0; ensures age == \old(age);also requires 0 <= a && a <= 150 || a < 0; ensures 65 <= age ==> ageDiscount;
Method Specification Inheritance:Extended Specification
Problem 3: Verification with OO features Subtyping Dynamic Dispatch
Approach [LN06] Supertype abstraction Validity:
Assumptions about Invariants, etc., Behavioral subtyping
Behavioral subtypingfrom specification inheritance
Supertype Abstraction
Reasoning about dynamic dispatch:
Gendered e = (Gendered)elems.next();if (e.isFemale()) {
//@ assert e.gender.equals(“female”);// ...
}
Supertype abstraction: Static type of e is Gendered Use specification from Gendered
Static Type’s Specification
public interface Gendered {
//@ model instance String gender;
//@ ensures \result == gender.equals(“female”);/*@ pure @*/ boolean isFemale();
}
Supertype Abstraction in General
Use static type’s specifications to reason about:
Method calls, Invariants, History constraints, Initially predicates
Supertype Abstraction in General
T o = /* create a new object */;
//@ assume o.ext_initT && o.ext_invT;
/* … */
//@ assert ; o.m();//@ assume ;//@ assume o.ext_invT && o.ext_hcT;
o.ext_preTm
o.ext_postTm
Reasoning withoutSupertype Abstraction?
Case analysis: Case for each potential dynamic type Can exploit dynamic type’s specifications
Case Analysis+ Supertype Abstraction Use instanceof for case analysis
Downcast, use supertype abstraction
/*@ requires p instanceof Doctor @ || p instanceof Nurse; @*/public boolean isHead(final Staff p) {
if (p instanceof Doctor) { Doctor doc = (Doctor) p; return doc.getTitle().startsWith(“Head”);} else { Nurse nrs = (Nurse) p; return nrs.isChief();}
}
Supertype Abstraction’s Soundness
Valid if: Invariants etc. hold as needed, and Each subtype is a behavioral subtype
assert Pre;
assume Pre && Inv;
assert Post && Inv;
assume Post;
Assumption about Invariants
Invariant Methodology
Potential problems:
Representation exposure
Reentrance
Relevant invariant semantics [Mül02,MPHL06]:
Ownership type system
Re-establish invariant when call
Guarantees:
invariant holds at start of method
Initially Predicates,History Constraints Similar problems? Similar solutions?
Behavioral Subtypes
Subtypes obey supertype specification Subtypes:
Refine method specifications Strengthen invariants, etc.
Method Specification Refinement with respect to T′
Notation: (pre′, post′ ) ⊒T′ (pre, post )
Refinement with respect to T′
pre
post
Refinement with respect to T′
pre
post
pre′
Refinement with respect to T′
pre
post
pre′
post′
Proving Method Refinements
Theorem 1. Suppose T′ ≤ T, andT′ ⊳ (pre′, post′ ), T ⊳ (pre, post ) specify m.
Then (pre′, post′ ) ⊒T′ (pre, post )
if and only if:
Spec(T′ ) pre && (this instanceof T′ ) pre′,
and
Spec(T′ ) \old(pre && (this instanceof T′ )) (post′ post ).
T o = /* create a new object */;
//@ assume o.ext_initT && o.ext_invT;
/* … */
//@ assert ; o.m();//@ assume ;//@ assume o.ext_invT && o.ext_hcT;
Validity of Supertype Abstraction:Client (Supertype) view
o.ext_preTm
o.ext_postTm
T o = new T′ ();
//@ assert o.ext_initT′ && o.ext_invT′;
/* … */
//@ assume ; o.m();//@ assert ;//@ assert o.ext_invT′ && o.ext_hcT′ ;
Validity of Supertype Abstraction:Implementation (Subtype) View
o.ext_postT′ m
o.ext_pre T′ m
Definition. Suppose T′ ≤ T. Then T′ is a strong behavioral subtype of T if and only if:
for all instance methods m in T, ⊒T′
whenever this has type T′ :ext_invT′ ext_invT,ext_hcT′ ext_hcT, andext_initT′ ext_initT.
Behavioral Subtyping for JML
ext_specT′ m
ext_specTm
Ensuring Validity
Method specification inheritancemust make refinements
`also’ must make refinements
also Makes Refinements
Theorem 2. Suppose \old is monotonic.Suppose T′ ≤ T, andT′ ⊳ (pre′, post′ ), T ⊳ (pre, post ) specify m.
Then (pre′, post′ ) ⊔T′ (pre, post ) ⊒T′ (pre,
post ).
also Makes Refinements
pre′
post && post′
pre && pre′
pre
postpost′
Specification Inheritance Forces Behavioral Subtyping
Theorem 3. Suppose T′ ≤ T . Thenthe extended specification of T′ is a strong behavioral subtype ofthe extended specification of T.
Proof: Use Theorem 2 and definition of extended specification.
Discussion
Every subtype inherits Every subtype is a behavioral subtype
Not all satisfiable Supertype must allow refinement
Unsatisfiable Refinements
pre′
post && post′
pre && pre′
pre
post
post′
Unrefinable Binary Method Specification /*@ also
@ ensures obj instanceof Gendered @ ==> (\result @ == gender.equals( @ ((Gendered)obj).gender)); @*/public /*@ pure @*/ boolean equals(/*@ nullable @*/ Object obj);
Says only gender mattersRefinements can’t use other attributes
Unrefinable Binary Method Specification
(f,f) (m,m)
(f,m) (m,f)
true
false
Better, Refinable Binary Method Specification /*@ also
@ ensures obj instanceof Gendered @ ==> (\result @ ==> gender.equals( @ ((Gendered)obj).gender)); @*/public /*@ pure @*/ boolean equals(/*@ nullable @*/ Object obj);
Says gender must be equalRefinements can use other attributes
Better, Refinable Binary Method Specification
(f,f) (m,m)
(f,m) (m,f)
true
false
Allowedresult
Related Work
Work with Naumann [LN06], basis for this talk.Proved exact conditions on behavioral subtyping for validity of supertype abstraction
Liskov and Wing [LW94] “subtype requirement” like supertype abstraction.Abstraction functions implicit in JML.
Several program logics for Java,[Mül02] [Par05] [Pie06] [PHM99],use supertype abstraction.
Work with Dhara [DL96]proved specification inheritanceforces behavioral subtyping.
More Related Work
Wills’s Fresco [Wil92] introduced specification inheritance.
Wing’s dissertation [Win83]combined specification cases like also.
Eiffel [Mey97] has behavioral subtypingand a form of specification inheritance.
America [Ame87] [Ame91] firstproved soundness with behavioral subtyping.
See survey with Dhara [LD00].
Future Work
Warn if attempt to strengthen preconditions [FF01].
Warn if subtype is unsatisfiable. Methodology for
history constraints and initially predicates
Conclusions
Supertype abstractionallows modular reasoning.
Supertype abstraction is valid if: methodology enforced, and subtypes are behavioral subtypes.
JML’s also makes refinements. Specification inheritance in JML
forces behavioral subtyping. Supertype abstraction
automatically valid in JML.
Acknowledgments
Thanks to David Naumann, William Weihl, Krishna Kishore Dhara, Cesare Tinelli, Don Pigiozzi, Barbara Liskov, Jeannette Wing, Yoonsik Cheon, Al Baker, Clyde Ruby, Tim Wahls, Patrice Chalin, Curtis Clifton, David Cok, Joseph Kiniry, Rustan Leino, Peter Müller, Arnd Poetzsch-Heffter, Erik Poll, andthe rest of the JML community.
Join us at...jmlspecs.org
Future Work on JML
Tools Java 1.5 support Eclipse support
Documentation Concurrency support Semantic details Theorem proving tie-ins, Static analysis tie-
ins Inference of specifications Tools that give more benefits
References[Ame87] Pierre America. Inheritance and subtyping in a parallel object-oriented language. In Jean Bezivin et al., editors, ECOOP ’87, European
Conference on Object-Oriented Programming, Paris, France, pages 234–242, New York, NY, June 1987. Springer-Verlag. Lecture Notes in Computer Science, volume 276.
[Ame91] Pierre America. Designing an object-oriented programming language with behavioural subtyping. In J. W. de Bakker, W. P. de Roever, and G. Rozenberg, editors, Foundations of Object-Oriented Languages, REX School/Workshop, Noordwijkerhout, The Netherlands, May/June 1990, volume 489 of Lecture Notes in Computer Science, pages 60–90. Springer-Verlag, New York, NY, 1991.
[BCC+05] Lilian Burdy, Yoonsik Cheon, David R. Cok, Michael D. Ernst, Joeseph R. Kiniry, Gary T. Leavens, K. Rustan M. Leino, and Erik Poll. An overview of JML tools and applications. International Journal on Software Tools for Technology Transfer, 7(3):212–232, June 2005.
[DL96] Krishna Kishore Dhara and Gary T. Leavens. Forcing behavioral subtyping through specification inheritance. In Proceedings of the 18th International Conference on Software Engineering, Berlin, Germany, pages 258–267. IEEE Computer Society Press, March 1996. A corrected version is ISU CS TR #95-20c, rlhttp://tinyurl.com/s2krg.
[FF01] Robert Bruce Findler and Matthias Felleisen. Contract soundness for object-oriented languages. In OOPSLA ’01 Conference Proceedings, Object-Oriented Programming, Systems, Languages, and Applications, October 14-18, 2001, Tampa Bay, Florida, USA, pages 1–15, October 2001.
[Hoa69] C. A. R. Hoare. An axiomatic basis for computer programming. Communications of the ACM, 12(10):576–580,583, October 1969.[Hoa72] C. A. R. Hoare. Proof of correctness of data representations. Acta Informatica, 1(4):271–281, 1972.[LD00] Gary T. Leavens and Krishna Kishore Dhara. Concepts of behavioral subtyping and a sketch of their extension to component-based
systems. In Gary T. Leavens and Murali Sitaraman, editors, Foundations of Component-Based Systems, chapter 6, pages 113–135. Cambridge University Press, 2000.
[Lei98] K. Rustan M. Leino. Data groups: Specifying the modification of extended state. In OOPSLA ’98 Conference Proceedings, volume 33(10) of ACM SIGPLAN Notices, pages 144–153. ACM, October 1998.
[LN06] Gary T. Leavens and David A. Naumann. Behavioral subtyping, specification inheritance, and modular reasoning. Technical Report 06-20b, Department of Computer Science, Iowa State University, Ames, Iowa, 50011, September 2006.
[LW94] Barbara H. Liskov and Jeannette M. Wing. A behavioral notion of subtyping. ACM Transactions on Programming Languages and Systems, 16(6):1811–1841, November 1994.
[Mey97] Bertrand Meyer. Object-oriented Software Construction. Prentice Hall, New York, NY, second edition, 1997.[MPHL06] Peter Müller, Arnd Poetzsch-Heffter, and Gary T. Leavens. Modular invariants for layered object structures. Science of Computer
Programming, 62(3):253– 286, October 2006.[Mül02] Peter Müller. Modular Specification and Verification of Object-Oriented Programs, volume 2262 of Lecture Notes in Computer Science.
Springer-Verlag, 2002.[Par05] Matthew J. Parkinson. Local reasoning for Java. Technical Report 654, University of Cambridge Computer Laboratory, November 2005.
The author’s Ph.D. dissertation.[PHM99] A. Poetzsch-Heffter and P. Müller. A programming logic for sequential Java. In S. D. Swierstra, editor, European Symposium on
Programming (ESOP ’99), volume 1576 of Lecture Notes in Computer Science, pages 162–176. Springer-Verlag, 1999.[Pie06] Cees Pierik. Validation Techniques for Object-Oriented Proof Outlines. PhD thesis, Universiteit Utrecht, 2006.[SBC92] Susan Stepney, Rosalind Barden, and David Cooper, editors. Object Orientation in Z. Workshops in Computing. Springer-Verlag,
Cambridge CB2 1LQ, UK, 1992.[Wil92] Alan Wills. Specification in Fresco. In Stepney et al. [SBC92], chapter 11, pages 127–135.[Win83] Jeannette Marie Wing. A two-tiered approach to specifying programs. Technical Report TR-299, Massachusetts Institute of Technology,
Laboratory for Computer Science, 1983.
Top Related