OO三单元总结__JML

一、关于JML

1、理论基础

JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。JML是一种行为接口规格语言(Behavior Interface Specification Language, BISL), 基于Larch方法构建。

JML主要用于两个方面:(1)开展规格化设计 (2) 怎对已有代码实现,书写规格,提高代码可维护性
更多细节可以参考here

2、基本语法

JML以javadoc注释的方式来表示规格,每行都以@起头。有两种注释方式,行注释和块注释。其中行注释的表示方式 为 //@annotation ,块注释的方式为 /* @ annotation @*/,annotaion为注释内容。JML一般位于被注释内容的上方。

JML中一些常见的语法成分:

关键字 说明
normal_behavior 后面为方法的正常行为
exceptional_behavior 后面为方法的异常行为
requires 前置条件,通常为对输入的限制
assignable 副作用范围限定,列出方法能够修改的类成员属性
ensures 后置条件,通常涉及返回值或操作前后类成员属性
signals 异常描述

JML常用的语法:

  • /@ pure @ / 表示方法是纯查询方法,执行不会有任何副作用
  • \result表达式:表示非void类型的方法执行获得的结果,即返回值。
  • \old(expr)表达式:评估expr中的对象在方法执行前后发生变化的情况。
  • \forall表达式:全称量词修饰的表达式,表示指定范围内的元素,全部满足相应约束。
  • \exist表达式:存在量词修饰的表达式,表示存在某个元素满足相应的约束。

方法规格&类型规格

  • 方法规格:包括前置条件、后置条件和副作用约定三个部分。前置条件是对方法输入参数的约束;后置条件是对方法执行结果的限制;副作用是指方法执行过程中对输入对象或this对象进行了修改。一个简单的例子如下,recordCredit方法要求正常输入的int变量z,取值在0到100之间,返回值为credits容器的长度,如果输入不满足要求会产生指定的异常:
public abstract class Student { 
        /** A specification that can't be satisfied. */  
        //@ public model non_null int[] credits;   
        /*@ normal_behavior    
             @ requires z >=0 && z <= 100;    
             @ assignable \nothing;    
             @ ensures \result == credits.length;
             @ also    
             @ exceptional_behavior    
             @ requires z < 0;    @ assignable \nothing;    
             @ signals_only IllegalArgumentException;
             @ also    
             @ exceptional_behavior    
             @ requires z > 100;    
             @ assignable \nothing;    
             @ signals_only OverFlowException;    
             @*/ 
    public abstract int recordCredit(int z) throws IllegalArgumentException, OverFlowException; }
  • 类型规格: 针对Java程序中定义的数据类型设计的限制规则。下面介绍两种限制规则:不变式限制(invariant)和约束限制(constraints)
    • 不变式(invariant): 要求在所有可见状态下都必须满足的特性,语法为 invariant P, invariant为关键词,P是谓词。

    • 状态变化约束(constraint): 对前序可见状态和当前可见状态的关系进行约束。
      参考下面的例子:

      public class ServiceCounter{    
        private /*@spec_public@*/ long counter;    
        //@ invariant counter >= 0;    
        //@ constraint counter == \old(counter)+1; 
      }

      对ServiceCounter类,要求在可见状态下,counter不能为负数,同时要求每次对counter的修改只能是增加1。

3、应用工具链(及相关使用)

(1) Openjml, SMT Solver

  • openjml可以对用静态或者运行时的方式对程序的行为进行检查。SMT solver则可以对JML进行理论检查,推导代码的正确性。z3, cvc4等SMT solver可以与OpenJML较好地配合使用。

  • 下载链接, 解压后可以找到相应的jar包和.exe文件

  • 使用方式1:命令行。这里展示windows的使用方式,linux和macos类似。

    java -jar <filepath>\openjml.jar -cp <classpath> -esc|-rac <target java file> -exec <solverpath>\z3-4.7.1.exe
    其中,-esc表示静态检查,-rac表示动态检查,只保留一个。 -cp表示需要添加的依赖(jar包等等)。我的windows10似乎只支持z3-4.7.1版本的solver。
  • 使用方式2:eclipse插件。虽然IDEA有能装,但是使用的时候蜜汁bug,就不介绍了。
    • 首先,Help->install new software, 安装openjml,链接:http://jmlspecs.sourceforge.net/openjml-updatesite 之后,Window->preference,对openjml的solver进行配置。

    • 配置完成后,选定文件,JML->ESC静态检查,RAC动态检查生成.class文件,结果如下:(报了很多的异常,不是很明白,另外跑得很慢很慢)

(2) JMLUnitNG

  • JMLUnitNG是基于TestNG的,为JML注释的java文件自动生成单元测试的工具。使用指南

  • 基本使用方法:

java -jar jmlunitng.jar [OPTIONS] path-list

其中,path-list是需要检查的文件,可添加的参数中比较重要的是-cp,与openjml使用类似

本次选取MyPath中的部分方法进行验证(对于一些JML语法不支持,只能验证一些简单的例子)

仅保留了isValid, getNode和size对应的JML

首先用javac进行编译,之后用opjml solver-rac, 使动态检查处于Enable状态,然后进行检验,具体可参考讨论区帖子

得到结果如下图:

二、架构设计

  • 第一次的架构完全模仿了指导书,仅实现了(实际有用的)方法,没有特别之处
  • 第二次作业与第一次相比,需要增加最短路径算法。为此,我单独准备了Matrix类,用于以变形邻接矩阵形式存储图的连接关系和算法实现,类图见下
  • 第三次作业增加了一些新的图算法和图的存储要求,为此我增加了3个新的似Matrix类,继承MultiMatrix类,用于存不同的图,但在MultiMatrix中同一使用了不拆点的算法。为了完成点的信息抽象,单独建立了Pathdistance类存储不同类型的"距离"值。类图见下

    关于图算法,我选择了采用不拆点的方式,重新定义距离,算是一种空间换时间的策略。关于优化,采用了局部更新图结构的策略,每次添加新的路径时,记录下路径中任意两点之间的距离,存入图中,如果出现比原有距离小的情况则认为图结构出现了更新,距离矩阵也需要跑Floyd更新。删除路径同理。这样的算法要求局部最优,即每个path添加进来时,必须保证已经求得任意两点之间距离是最短的。

    三、bug情况

  • 自测不积极,强测两行泪
  • 第一次JML作业中,compareTo方法由于疏忽将某一处的返回值-1误写为1,导致大量涉及到路径比较的指令结果出错,boom
  • 后两次作业加强了Junit测试和脚本测试的覆盖程度,并且进行了运行时间的测试,没有出现bug

四、心得体会

个人觉得,尽管JML在理论方面相对完善,在实际应用中却存在着工具不完善、使用不方便的问题。从JML的层次进行检查比代码层次的测试要困难得多,这是可以理解的,但是openjml, JMLUnitNG等工具存在缺陷限制了JML的一些应用。只有对工具进行更新、支持更多的语法,才会有更多的开发者使用JML。

猜你喜欢

转载自www.cnblogs.com/frozen-blog/p/10903502.html
今日推荐