zoukankan      html  css  js  c++  java
  • OpenJML入门

    OpenJML 获取

    下载

    OpenJML下载可以通过其github仓库获取。传送门

    使用

    下载完成后,可以直接使用命令行进行操作,但是比较麻烦。这里提供两个版本的辅助文件简化操作

    Linux

    # filename : openjml
    #!/bin/bash
    java -jar path/to/openjml.jar "$@"
    

    其中jar包的路径需要自行修改。

    Windows

    ::openjml.bat
    @echo off
    
    set java=java -jar "%~dp0openjml.jar" -noPurityCheck
    set prove=-prover cvc4 -exec "%~dp0Solvers-windowscvc4-1.6.exe"
    set runtime=-cp %~dp0jmlruntime.jar;
    
    set allparam=
    set rac=
    
    :param
    set str=%1
    if "%str%"=="" (
        goto end
    )
    if "%str%"=="-rac" (
    	set rac=rac
    )
    if "%str%"=="-prove" (
    	set str=%prove%
    )
    set allparam=%allparam% %str%
    shift /0
    goto param
    
    :end
    if "%allparam%"=="" (
        goto eof
    )
    
    rem remove left right blank
    :intercept_left
    if "%allparam:~0,1%"==" " set "allparam=%allparam:~1%"&goto intercept_left
    
    :intercept_right
    if "%allparam:~-1%"==" " set "allparam=%allparam:~0,-1%"&goto intercept_right
    
    :eof
    %java% %allparam%
    set filename=
    if "%rac%"=="rac" (
    	:input
    	set /p filename=Input file name:
    	if "%filename%"=="" (
    		goto input
    	)
    	java %runtime% %filename%
    )
    
    
    pause
    

    用户可以将上述代码拷贝到解压后的文件夹中,然后将该文件夹加入环境变量。即可通过命令行调用openjml命令了。这里为了简化验证时的参数传递,提供了一个-prove参数。用户指定这一参数后,程序将选定prover并执行。

    Parsing and Type-checking

    OpenJML最基本的功能就是对JML注释的完整性进行检查。检查包括经典的类型检查、变量可见性与可写性等。通过命令行使用OpenJML时,可以通过-check参数(缺省)指定类型检查。

    openjml [-check] options files
    

    举例来说

    public class main {
    	/*@
    	  @ require args != null
    	  @*/
    	public static void main(String[] args) {
    		System.out.println(args);
    	}
    }
    

    运行语法检查后报错

    C:>openjml main.java
    main.java:17: 错误: 需要';'
              @ require args != null
                            ^
    main.java:17: 错误: 找不到符号
              @ require args != null
                ^
      符号:   类 require
      位置: 类 main
    2 个错误
    

    类型检查检测出了注释中的两处错误。分别更改后的程序如下

    public class main {
    	/*@
    	  @ requires args != null;
    	  @*/
    	public static void main(String[] args) {
    		System.out.println(args);
    	}
    }
    

    再次运行后即可通过检查。

    Extended Static Checking

    类型检查只能确保jml注释的格式正确,但是对规格内容不进行检查。下述程序中明显违背了规格的描述,但是类型检查仍然通过了。

    public class main {
    	/*@
    	  @ requires a != 0 && b != 0;
    	  @ ensures 
    esult <= 1 && 
    esult >= 0;
    	  @*/
    	public static int fun(int a, int b) {
    		return a > b ? 1 : 0;
    	}
    	public static void main(String[] args) {
    		fun(1, 0);
    	}
    }
    

    为了对规格内容进行检查,需要使用-esc参数

    C:>openjml -esc -prove main.java
    main.java:10: 警告: The prover cannot establish an assertion (Precondition: main.java:6: 注: ) in method main
                    fun(1, 0);
                       ^
    main.java:6: 警告: Associated declaration: main.java:10: 注:
            public static int fun(int a, int b) {
                              ^
    main.java:3: 警告: Precondition conjunct is false: b != 0
              @ requires a != 0 && b != 0;
                                     ^
    3 个警告
    

    这里需要注意,静态检查需要指定prover。在上述Windows版的批处理函数中,默认指定了一个prover。用户也可以使用-prover等参数指定自定义检查器。

    那么esc是如何完成的呢?好奇的话可以通过-progress参数或-verboseness参数来查看检查的具体过程。下面截取了部分输出

    C:>openjml -esc -prove main.java -verboseness=3
    ...
    STARTING PROOF OF main.main(java.lang.String[])
    /*@
      public behavior
        requires args != null;
        signals_only java.lang.RuntimeException;
        assignable everything;
        accessible everything;
     */
    
    {
      fun(1, 0);
    }
    ...
    

    可以看出OpenJML在验证前会首先重整规格,而后针对性生成测试程序。由于生成程序过长,可以在本地尝试。此处使用的是-verboseness=3,如果使用 4 将会输出大量信息。

    Runtime Assertion Checking

    使用-rac选项可以执行运行时检查。上述批处理文件中存在 bug,第一次输入文件名时可能会要求再次输入。

    C:>openjml -rac main.java
    Input file name:main
    main.java:10: 警告: JML precondition is false
                    fun(1, 0);
                       ^
    main.java:6: 警告: Associated declaration: main.java:10: 注:
            public static int fun(int a, int b) {
                              ^
    
    

    这时会自动运行生成出来的.class文件,但经过反汇编后我的.class文件并不能编译。因此目前还没有看懂rac的具体流程。此外,-rac选项有许多补充选项,功能十分丰富,大家可以多多尝试。

    参考

    OpenJML 基本使用 伦泽标

  • 相关阅读:
    1523. K-inversions URAL 求k逆序对,,,,DP加树状数组
    Football 概率DP poj3071
    Collecting Bugs poj2096 概率DP
    E. Exposition
    Subsequence
    D. How many trees? DP
    hdu 1542 线段树 求矩形并
    Huge Mission
    2013 ACM/ICPC Asia Regional Chengdu Online hdu4731 Minimum palindrome
    008 jackson的一些使用记录
  • 原文地址:https://www.cnblogs.com/lutingwang/p/openjml_basic.html
Copyright © 2011-2022 走看看