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-windows\cvc4-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 \result <= 1 && \result >= 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 基本使用 伦泽标
OpenJML入门的更多相关文章
- BUAA OO 2019 第三单元作业总结
目录 总 JML规格化设计 理论基础 工具链 规格验证 验证代码 代码静态检查 自动生成测试样例 生成结果 错误分析 作业设计 第九次作业 架构 代码实现 第十次作业 架构 代码实现 第十一次作业 架 ...
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- Oracle分析函数入门
一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...
- Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数
上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...
- Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数
上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...
- Angular2入门系列教程4-服务
上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
随机推荐
- 刷题3:给定一个数组 nums,判断 nums 中是否存在三个下标 a,b,c数相加等于targe且a,b,c不相等
题目: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,下标 ,a ,b , c 对应数相加等于 targe 找出所有满足条件且不重复的三元组下标 解析: ...
- 快速激活Navicat Premium 12
Navicat Premium 12是一套数据库开发管理工具,支持链家MySQL.Oracle.SQL server等多种数据库,快速便捷创建.管理和维护数据库 一.下载 https://www.na ...
- Android相关属性的介绍:android:exported = true
在Activity中该属性用来标示:当前Activity是否可以被另一个Application的组件启动:true允许被启动:false不允许被启动. android:exported 是Androi ...
- MYSQL事务的开启与提交
MYSQL 事务处理主要有两种方法: 1.用 BEGIN, ROLLBACK, COMMIT来实现 BEGIN 开始一个事务 ROLLBACK 事务回滚 COMMIT 事务确认 2.直接用 SET 来 ...
- DOM 是什么,Document Object Model,文档对像模型
#为什么会想起来写这个 在写dynaTrace Ajax的时候,写到这个是个前端性能测试工具,这个工具能记录请求时间,前端页面渲染时间,DOM方法执行时间,以及JavaScript代码解析和执行时间. ...
- Springboot属性加载与覆盖优先级与SpringCloud Config Service配置
参考官方文档:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config. ...
- 进行编译时提示'error: unrecognized command line option "-std=gnu11"'如何处理?
答: 说明编译器不支持此选项,那么在Makefile中替换此选项-std=gnu11 替换成-std=gnu99或-std=c99或-std=c11等,主要看编译器都支持哪些编译选项,笔者的支持-st ...
- 数据分析入门——pandas之合并函数merge
merge有点类似SQL中的join,可以将不同数据集按照某些字段进行合并,得到新的数据集 1.参数一览表: 2.一对一连接:默认情况下,会按照相同字段的进行连接 例如有相同字段emp的两个df,m ...
- Nginx记录-Proxy_pass多个应用配置(转载)
1. 在http节点下,加入upstream节点. upstream linuxidc { server 10.0.6.108:7080; server 10.0.0.85:8 ...
- Nginx 反向代理 一个IP代理多个域名,不区分端口,类似windows虚拟机。
简介: IP有限,所以我们以前使用端口来区分不同的虚拟主机,提供不同的WEB服务. 小范围还凑活,一旦规模扩大,地址记不住了吧?端口记不住了吧? 这个时候我们可以使用DNS,域名解析,毕竟记名字比记I ...