JML: A Modular Specification Language for Java Enhancing Verification and Design
The Java Modeling Language (JML) is a formal specification language designed for Java that allows for the precise definition of program behavior through annotations and contracts. It supports modular reasoning and promotes effective, practical design while facilitating verification through Hoare-style preconditions and postconditions, type invariants, and field specifications. JML is widely supported by various tools in the research community, enhancing its applicability in existing code bases. Engage with over 125 published papers and join a collaborative community dedicated to practical formal methods for Java.
JML: A Modular Specification Language for Java Enhancing Verification and Design
E N D
Presentation Transcript
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
fieldspecification method behavior specification Example JML Specification public classAnimal implements Gendered {protected /*@ spec_public @*/int age = 0; /*@ requires0 < yrs;@ensuresage == \old(age + yrs); @*/public void older(final int yrs){ age = age + yrs; } /* … */ }
BehavioralInterface Specification JML Specification Syntactic Interface Functional Behavior Java Code
Behavioral Interface Specification /*@ requires0 < yrs;@ensuresage == \old(age + yrs); @*/public void older(final int yrs); requiresyrs > 0;ensures age == \old(age) + yrs; public void older(final int yrs); public void older(final int yrs){ age = 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 Warnings JML Annotated Java ESC/Java2 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; } } } jmldoc Web pages Daikon jmlunit Data trace file Unit tests jmlc JACK, Jive, Krakatoa,KeY,LOOP Bogor Class file Correctness proof Model checking XVP
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 classAnimal implements Gendered { protected boolean gen; //@ in gender; /*@ protected represents gender @ <- (gen ? “female” : “male”);@*/ // ...
Use of Model Fields public classAnimal implements Gendered { protected boolean gen; //@ in gender; /*@ protected represents gender @ <- (gen ? “female” : “male”);@*/ public/*@ pure @*/ boolean isFemale(){ return gen; } // ...
Correctness with Model Fields isFemale’sspecification “female” gender: true represents == isFemale’scode gen: true true
Requires Clauses public classAnimal implements Gendered { protected boolean gen; //@ in gender; /*@ protected represents gender @ <- (gen ? “female” : “male”);@*/ //@ requires g.equals(“female”)||g.equals(“male”);//@ ensuresgender.equals(g);public Animal(final String g){ gen = g.equals(“female”); }
Model of Method Specifications public interfaceT {//@requirespre;//@ensurespost;voidm();} T⊳(pre, post)
post m() pre Model of Method Specifications output post-state input pre-state
spec_publicShorthand Instead of: //@ public model int age;protectedint_age = 0;//@ in age;//@ protected represents age <-_age; Write: protected /*@ spec_public @*/int age = 0;
Specification Cases, ‘also’ public classAnimal implements Gendered {protected/*@ spec_public @*/int age = 0; /*@ requires0 <= a && a <= 150;@ensuresage == a; @ also@requiresa < 0;@ensuresage == \old(age); @*/public void setAge(final int a){ if (0 <= a) { age = a; } }
Join of Specification Cases requires0 <= a && a <= 150;ensuresage == a;alsorequiresa < 0;ensuresage == \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 post &&post′ post pre′ pre pre &&pre′
Join of Specification Cases, ⊔S If T′ ⊳ (pre′, post′), T⊳ (pre, post), S ≤ T′, S ≤ T, then (pre′, post′)⊔S (pre, post) =(p, q) wherep=pre′||preandq=(\old(pre′)==>post′) && (\old(pre)==>post )andS⊳ (p, q)
Type Specifications:Invariants import java.util.*; public classPatient 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 Tortoise invariant 0 <= age && age <= 150; FemalePatient
Initially public classPatient 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 classPatient 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
added_spec T m T’s Added Specifications Declared in T (without inheritance): added_invT invariant added_hcT history constraint added_initT initially predicate m’s specification Other Notations supers(T ) = {U | T U } methods(T) = { m | m declared in TT}
added_spec U m ext_spec T m Specification Inheritance’s Meaning:Extended Specification of T • Methods: for all mmethods(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) }
Invariant Inheritance public classFemalePatient extends Patient { //@ public invariantgender.equals(“female”);// … } • Extended invariant: added_invGendered && added_invAnimal && added_invPatient && added_invFemalePatient
Invariant Inheritance public classFemalePatient extends Patient { //@ public invariantgender.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 classFemalePatient extends Patient { //@ public invariantgender.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 classAnimal implements Gendered { // … /*@ requires0 <= a && a <= 150;@ensuresage == a; @ also@requiresa < 0;@ensuresage == \old(age); @*/public void setAge(final int a) { /* … */ }
Method Specification Inheritance:Subtype’s added_spec public classPatient extends Animal { // … protected/*@ spec_public @*/boolean ageDiscount = false; //@ in age;/*@ also@requires 0 <= a && a <= 150 || a < 0; @ ensures65 <= age ==> ageDiscount;@*/public void setAge(final int a) {super.setAge(a);if (65 <= age) { ageDiscount = true; }}
added_spec added_spec ext_spec Patient Animal Patient setAge setAge setAge Method Specification Inheritance:Extended Specification = ⊔Patient{ , }
Method Specification Inheritance:Extended Specification requires0 <= a && a <= 150;ensuresage == a;alsorequiresa < 0;ensuresage == \old(age);also requires 0 <= a && a <= 150 || a < 0;ensures65 <= age ==> ageDiscount;
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()) {//@ asserte.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
o.ext_pre T m o.ext_post T m Supertype Abstraction in General To = /* create a new object */; //@ assumeo.ext_initT && o.ext_invT; /* … */ //@ assert;o.m();//@ assume ;//@ assumeo.ext_invT && o.ext_hcT;
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 /*@ requiresp instanceof Doctor@ || p instanceof Nurse; @*/publicboolean isHead(final Staff p) {if(p instanceof Doctor) { Doctor doc = (Doctor) p;returndoc.getTitle().startsWith(“Head”); } else { Nurse nrs = (Nurse) p;returnnrs.isChief(); }}
Supertype Abstraction’s Soundness Valid if: • Invariants etc. hold as needed, and • Each subtype is a behavioral subtype
Assumption about Invariants assert Pre; assume Pre && Inv; assert Post && Inv; assume Post;
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.