JML Angelo Gargantini Linguaggi di programmazione per la sicurezza, Università di Milano, Crema, 2005 Introduzione a JML è un insieme di tool e di tecniche per il design by contract in Java ed altro ● disponibile su web: • http://www.cs.iastate.edu/~leavens/JML/ • www.jmlspecs.org ● JML sintassi ● ● ● ● Per rendere JML facile da usare le annotazioni JML vengono aggiunte come commenti nel file .java tra /*@ . . . @*/, o dopo //@. le proprietà sono scritte come espressioni boolean di java con alcuni operatori in più: \result, \forall, \old, ==>, ... e alcune parole chiave requires, ensures, invariant, ... Using JML we specify and check properties of the Java program itself, not of some model of our Java program. Ie. the Java program itself is our formal model. Pre- and postconditions Pre- and post-conditions for methods: /*@ requires amount >= 0; ensures balance == \old(balance) - amount && \result == balance; @*/ public int withdraw(int amount) { ... } Here \old(balance) refers to the value of balance before execution of the method. Altri esempi JML specs can be as strong or as weak as you want. /*@ requires amount >= 0; ensures true; @*/ public int debit(int amount){ ... } This default postcondition “ensures true” can be omitted. Esempio con <==> //@ ensures \result <==> j < n; public boolean minore(int j, int n) { return j < n; } non_null Many invariants, pre- and postconditions are about references not being null. non_null is a convenient short-hand for these. public class Directory { private /*@ non null @*/ File[] files; void createSubdir(/*@ non null @*/ String name){…} Directory /*@ non null @*/ getParent(){…} assert An assert clause specifies a property that should hold at some point in the code, eg. if (i <= 0 || j < 0) { ... } else if (j < 5){ //@ assert i > 0 && 0 < j && j < 5; ... } else { //@ assert i > 0 && j > 5; ... } assert ● ● JML keyword assert now also in Java (since Java 1.4). Still, assert in JML is more expressive, for example in ... for (n = 0; n < a.length; n++) if (a[n]==null) break; /*@ assert (\forall int i; 0 <= i && i < n; a[i] != null); @*/ Quantifiers ● JML supports several forms of quantifiers Universal and existential (\forall and \exists) – General quantifiers (\sum, \product, \min, \max) – Numeric quantifier (\num_of) Esempi – ● ● (\forall Student s; juniors.contains(s); s.getAdvisor() != null) (\forall Student s; juniors.contains(s) ==> s.getAdvisor() != null) Esempio quantificatori /** Exercise 1: find the minimum element in an array. */ /*@ requires a != null && a.length >= 1; @ ensures (\forall int i; 0 <= i && i < a.length; \result <= a[i]) @ && (\exists int i; 0 <= i && i < a.length; \result == a[i]); @*/ public static int find_min (int a[]) Benefici di JML ● ● ● ● JML specifications provide explicit documentation of contracts and invariants Writing JML specs for code, you make explicit assumptions and considerations that have gone into the design of code Such JML specifications make it easier to understand code and should help to convince yourself and others that nothing can go wrong. Such JML specifications can be used by tools . Tools per JML 1.JML compiler (jmlc): compila file java per avere class instrumentati 2.JML/Java interpreter (jmlrac): performs checks for all JML assertions at runtime: any assertion violation results in a special exception. 3.Extended static checking with escjava2: proves JML assertions at compile time 4.JML/JUnit unit test tool (jmlunit) 5.HTML generator (jmldoc) 6.Altri tool .... Compilatore JML (jmlc) ● Uso testuale $ jmlc Person.java produces Person.class $ jmlc –Q *.java produces *.class, quietly $ jmlc –d ../bin Person.java produces ../bin/Person.class Eseguire il codice compilato con jmlc ● ● Must have JML’s runtime classes (jmlruntime.jar) in Java’s boot class path Automatic if you use script jmlrac, e.g., $ jmlrac PersonMain Come installare JML ● Scarica jmlXXX.tar.gz dal sito di JML – – ● Oppure jml.tar.gz dal sito web del corso sottodirectory codice Oppure da titano Unzippalo su c:\ in modo di avere una directory JML che contenga tutto – – – c:\jml -> tutto le sotto directory di jml c:\jml\ c:\jml\bin -> programmi veri e propri Come eseguire JML ● ● ● Scrivi la tua classe (esempio file My.java) nella directory c:\JML\bin Compilala con jmlc -> prossimo lucido Esegui il My.class nella finestra dos, fai cd fino a c:\JML\bin ed esegui jmlrac My Compilare jml ● ● Testualmente Con interfaccia grafica: – Doppio click su c:\JML\bin\jml-release.jar ● ● ● Seleziona la directory c:\JML\specs che contiene le specifiche jml delle librerie Seleziona jml checker se vuoi controllare la sintassi Seleziona jmlc se vuoi utilizzare il jml compiler per produrre il file .class Esercizio ● findMin Esercizio 2 ● Scrivi un metodo che ordina un array di interi – – – – Scrivi la classe con il metodo main e il metodo (per ora vuoto) ordina(int[] a){} Scrivi le precondizioni e le postcondizioni Prova a chiamare il metodo nel main, compila ed esegui e controlla che le pre/post condizioni siano non rispettate Alla fine implementa il metodo Esercizio JML/JUnit ● ● Scrivi l'intestazione di un metodo che calcola il resto della divisione tra due numeri (non scrivere per ora l'implementazione) Junit: Scrivi dei casi di test con Junit – ● ● Esegui i test e nota che alcuni (se non tutti) i test falliranno JML: Scrivi le precondizioni e le post condizioni Prova a richiamare il metodo (nel main) – – Con le precondizioni non valide Compila ed esegui in JML (con jmlc e jmlrac) ● Modifica ora la classe – – ● Con le precondizioni valide (ma le post condizioni non valide, visto che non hai ancora implementato il metodo Esegui il codice in JML: cosa osservi? Implementa il metodo in modo corretto – – esegui i casi di test con Junit Esegui i casi di test con JML Altri esempi ● ● ● ● ● Divisione intera tra due numeri Algoritmo che dato un array V di numeri restituisce un numero in V che non sia il massimo Ordinamento di un array di stringhe Ordinamento di un array di interi Dato una stringa, restitusce la stessa stringa ma con la prima lettera maiuscola.