当前位置:论文写作 > 硕士论文 > 文章内容

作业论文范文 作业有关论文参考文献范文5000字有关写作资料

主题:作业 下载地址:论文doc下载 原创作者:原创作者未知 评分:9.0分 更新时间: 2024-02-26

作业论文范文

《基于A的Ja作业辅助批阅工具的实现》

该文是有关作业本科论文范文与A和作业和辅助和批阅和工具有关在职研究生论文范文.

摘 要: 学习编程离不开大量的实践训练,但批阅学生提交的代码却是一件相当费神耗时的工作.Ja教学大都围绕其功能强大的标准类库来组织安排,并通过相应练习使学生熟练掌握.为了提高效率,设计了一个作业辅助批阅工具,它能对Ja类文件进行自动修改,在运行时获取关键类库的使用信息,了解它们的调用频次、先后次序、所用参数及返回值,可帮助理解程序逻辑,评判学生对教学内容的掌握程度.

关键词: Ja类文件,A,代码批阅,计算机辅助教学

中图分类号:TP399 文献标识码:A 文章编号:1006-8228(2020)01-53-04

Abstract: Coding is essential for learning a new programming language. However, for the instructors, it is very time-consuming and tedious to read over all of the code submitted by the students. The syllabus of Ja programming consists of using its powerful standard libraries, accompanied with corresponding practical coding projects. A tool is designed to help the instructors to improve their code review efficiency. This tool is able to automatically modify the Ja class files and return the usage of the class libraries, including their calling frequency, calling order, parameters and return values. This tool is helpful for understanding the logic of the code from students and judging their level of understanding.

Key words: Ja class file; A; code review; CAI

0 引言

Ja多年来一直是软件开发的首选语言,也是计算机专业学习的重点,对相关知识和开发能力都有较高要求,因此需要安排充实的教学内容,进行有效的训练实践.对于语法已入门的学生,教学通常是围绕着各种类库展开的.特别是JDK提供的标准类库,功能丰富全面、使用方便高效.从输入输出到集合框架、多线程、网络、数据库,各种功能都是通过使用相应对象,调用适当方法来实现的.即使是JaEE、云计算等进阶内容,也大都归结为对特定类库和框架的学习.这些内容的教学都需要有针对性地安排大量实践,而学生的掌握程度,也要通过批阅提交的作业,查看相应API的使用情况才能知晓.因此准确全面、高效及时地处理学生作业,就变得非常重要.

阅读他人程序,从来就不轻松.那些真正能训练和体验面向对象编程的作业,处理的问题和对应的程序结构都较复杂,代码规模大,处理流程多变,运行逻辑不是一眼能看清的.况且每个学生都有自己的编程风格和习惯,审阅这些代码相当劳心费力,如班级的人数再多一点,就非常辛苦了.过去的应对办法,要么是不管代码只看最后运行结果,要么是仅抽选少数几份作业批阅.它们都难以切实了解学生的学习情况,对教学效果的评估很容易产生偏差.而且如被学生察觉这种状况,对师生间的信任、交流、配合也是有害的.

那么如何才能既省時省力,又全面准确地检查学生的作业情况呢?我们的建议是批阅时多关注作为教学重点的那些核心API的使用,因为作业的目的就是要通过训练来掌握它们,它们通常也是程序处理的关键步骤.当然收集这些信息应该极其方便,最好是全自动的,不用在文本中搜索查找.我们设计了一个工具达到此目的,它会在程序运行中虚拟机执行类装载时对某些指令作适当修改,让它在完成相应操作的同时也输出必要信息.这样程序一运行,使用了哪些API、其顺序频度、具体数据等一目了然,从中不难推测它的设计思路,明确相关内容的掌握程度.

1 类文件结构和A工具

要修改Ja虚拟机指令,必须对Ja类文件结构有所了解.它有统一紧凑的层次格式[1],简化后的结构如图1所示,包含了类本身、全部的字段成员和方法成员信息,大量细节依靠相关属性来描述,所有常数和文字信息都通过对常量池的下标引用来表达.

我们要修改的代码在相应方法的Code属性中,主要部分是由bytecode顺序排列形成的字节数组,其中既有分支转移及异常捕捉等复杂结构,又隐含了运行中对局部变量和操作数栈的反复使用.它还包含多种属性,有局部变量的相关信息、程序行与代码的对应关系、还有程序员相当陌生的程序装载时的代码验证支持.它们相互联系对照,要直接在其中修改代码,既困难又易错.为此我们借用了一个使用广泛、高效方便的开源工具A.

A是Ja字节码的分析、生成、变换工具[2],它对类内成员的增删改、对代码内各指令的查找变换都进行了优化,隐藏了对常量池的操作,允许引入指令跳转、划定区域所需要的地址标号,能自动计算运行时Frame的容量、代码验证用的StackMapTable等.针对类文件的复杂结构,A采用Visitor设计模式,提供了基于事件和基于对象的两套API.前者简单快捷,但必须按序、即时地处理类内各元素.后者在内存中将各元素组织成树型结构,便于根据上下文自由修改.A提供下列核心部件[3].

● ClassVisitor、FieldVisitor、MethodVisitor等抽象类:定义了处理类内各种元素的visit方法签名,用户通过子类可实现对类内部各种成员的过滤、变换、增补等操作.它们还可接受另一Visitor对象,组成处理链,实现对元素的后续处理.

● ClassNode、FieldNode、MethodNode:是以上各Visitor的子类,定义了记录类内部各种元素的数据结构和对应的visit方法,用于实现基于对象的处理方式,在变换修改后还能用accept方法发起后续处理.

● ClassReader:它有accept方法,能接受Visitor对象,并执行对指定类文件内部结构的解析,进而驱动该对象执行相应方法进行处理.

● ClassWriter:是ClassVisitor的子类,执行相应方法能构造出对应类内元素的二进制表示,最后调用toByteArray方法,即可获得完整的类文件.

使用A时要将Reader、自定义的Visitor和Writer串接在一起,有时甚至形成多路结构,共同完成较复杂的处理.图3就是对作业代码进行修正变换所采用的结构,它会在代码中搜寻指定的指令和结构,进行必要的修改与添加.

2 类文件的修改变换

2.1 方法调用指令及变换方案

程序中使用类库主要是通过调用它提供的方法.Ja虚拟机有5种方法调用指令,INVOKEVIRTUAL和INVOKEINTERFACE分别调用类内定义和接口定义的动态绑定方法;INVOKESPECIAL调用无需动态绑定的方法;它们都通过某个对象执行,INVOKESTATIC调用不使用对象的类方法;INVOKEDYNAMIC目前除了lambda表達式外,Ja程序中并不使用.这些指令内都标明了方法的名称、类型及所在类在常量池中的索引,因此在代码中查找和修改特定的调用指令是比较简单的.

Ja虚拟机执行这些指令时都会在当前线程的堆栈顶创建一个Frame作为运行环境,其中包含局部变量区和操作数栈.方法调用指令前应先有指令将所需参数按序压入操作数栈,如是对象方法,首个参数一定是隐含的this引用.调用执行时这些参数被转录至新的Frame,作为前几个局部变量,在代码中得到处理.调用完成后将撤消该Frame,如有返回结果,它会出现在原Frame的操作数栈顶.

要在使用指定的API时获得信息,就要找到对应调用指令加以修改.比如对于正则表达式,通常关心其模式字符串的使用是否正确,这就要考察Pattern类的compile方法.最简单的办法是将该调用指令替换为对名为_compile的一个新方法的调用,由它再去调用原来的Pattern.compile,但额外会输出需要的信息,比如作为参数的模式字符串等.新方法保持与原方法的参数及返回完全一致,这样调用指令前后无需再作其他修改,只要在代码中引入新的_compile方法就可以了.使用这种修改调用指令的方法就可方便地获取所有要关注的API的使用信息.

除了主动调用类库的方法外,应用程序可能还要提供某些接口或抽象类规定的实现代码,比如Comparator接口就需要完成compare方法,它是被调用的.有时候了解它们的执行,考察其参数和返回结果,对理解整个程序也很有意义.为此可使用另一种替换方法,假如要了解compare方法的被调用情况,可将类文件中的原实现代码改名为_compare,另生成一个替代的compare方法,它会调用被改名的_compare来实现功能,但还能输出需要的信息,这样就能知道比较操作的时机、次数、每次比较的值和结果等.

2.2 标注变换点

采用这种方案,必须事先声明关注哪些方法,怎么输出信息,为此要按图2的样例代码所示定义CheckItems类.它通过一些自定义的标注指出关注的方法,@Item1和@Item2分别针对上述主动调用和被动调用的情形.它们都要写出完整的方法名,后面再紧跟处理方法,其中除了执行原本的调用外,还说明怎么输出信息.这些引入的代码会按前述方案进行处理,有些要改名,会用无冲突的名字代替.但这些方法的参数和返回类型必须和原方法完全一致,由于其中所有的方法调用都改换成了类方法调用,所以如果原来是对象方法,其隐含的this引用也要作为第一个参数显式写出,如图2所示.

CheckItems的父类是Check,它为处理和保存调用信息提供了一些通用方法.

● 打开并管理一输出流,提供print()和println()等方法,用来记录需要的信息.

● 提供fline()方法,返回调用点所在的源文件名和行号,可帮助区分同一方法在不同地点的调用,也有利于源文件阅读时的查找.

● 如果参数或返回值是基本类型或字符串,可直接输出,其意义很明晰.但对引用型变量t,则应使用obj(t)方法,它返回一个由类型和序号构成的、较容易理解的名称,如Thread1、Pattern3等,还保证同一引用一定获得同一名称,有助于在考察流程时确定各对象前后的同一性.

● 如果对象t是自定义类型,还可用val(t)获得其内部各字段的名字和值,比如对学生定义的日期类型,可能会输出{year:2019,month:1,day:1},这样可以切实了解代码运行中的数据细节及其变化,对分析、理解程序是非常必要的.

如果要考察特定对象的生成情况,也可在其构造方法的调用指令中,进行类似地修改替换,获得信息输出.但构造方法在类文件中被命名为<init>,不是合法的Ja标识符,需要做些特殊处理.如图2样例代码中的new Thread()所示,标注中仍指明替换<init>方法,但代码中用newobj()代替,它只是占位符,实际变换后仍改为调用<init>,当然在此前还要添加指令完成相应参数在操作数栈的准备.

在CheckItems类中还可根据需要引入一些状态变量来控制信息输出.比如对循环中的操作,有时只要查看前几次调用或最后的调用,有时只需统计调用次数,通过引入变量就能实现这些控制.图2的样例代码就统计了compare方法的调用次数,并仅对前三次输出.由此需引入对这些状态变量进行初始化和终极处理的begin和end方法,会在每份作业批阅的开始和结尾处执行.

对多线程相关作业,常常还关心用synchronized指示的对象锁的状态.该保留字在语法上有两种用法:置于方法定义前或组成一个代码块,对应地在类文件中也有两种处置[4]:在对应方法的标记中标志;用MONITORENTER/MONITOREXIT指令划出加锁区间,虚拟机运行时会相应的进行加/解锁操作.批阅作业时如希望了解这些情况,可在CheckItems类中加@LockInfo标注,代码处理时就会在合适位置插入指令,执行时就可获得加/解锁的时机、运行的线程、被锁的对象等信息.

批阅学生作业当然很希望了解他们的设计,有哪几个类、每个类的内部结构等.虽然可以查阅源代码,但要打开不同的文件再翻阅查找,还是比较费事.为此可在CheckItems类中加@MemberInfo标注,将会在处理类文件时先输出每个类的梗概信息,包括它们的继承/实现关系、所有字段和方法成员的名字、类型、访问控制等内容.这样就大概了解了其设计结构,对理解后续运行时输出的信息也有帮助.

2.3 代码变换器結构

有了CheckItems文件,就明确了需要考察的方法调用以及对应的信息输出方式,现在只需有一个代码变换器,将这些内容“织入”到学生提交的作业中,代码一经执行,那些关键步骤就被记录下来.通过查看这些信息,就能了解学生的学习情况.

代码变换器利用A提供的各种工具类构建,结构如图3所示.其中Reader2读入CheckItems,将其中内容存于Node对象中,并向Visitor1指出需要进行变换的方法.Reader1能读入作业中的各个class文件,解析后交Visitor1处理,Visitor1如发现匹配的方法,将按约定修改名称、指令, 再送至Writer,同时将需要补充的内容告诉Visitor2.Visitor2从Node中取得相应元素,作必要修改后也送至Writer.最后由Writer综合这些输入,构造出新的、能输出需要信息、完整可运行的二进制类文件.

实际批阅作业时将全班的代码组织在一个子目录中,每人是独立的包或jar文件,控制程序将逐个处理它们.对每份作业,生成一个自定义的类装载器,负责装载学生作业代码并利用上述变换器进行必要转换.在调用main()启动运行后,其输出的信息将送至指定文件.为避免处理过程脱离控制,变换器还将拦截Runtime和System 类的exit或halt调用,将其转换为能被控制程序捕捉的异常.代码变换器还会把代码中所有的标准输出也转向至同一指定文件,这样该程序的设计结构、运行过程中的关键信息和运行结果都被放置在一起,理解、评判学生作业情况就很方便了.

3 结束语

有了这一作业批阅辅助工具,可以大大提高工作效率.对于稍有规模的程序,要理解其思路,少不了要来回参照,分层拆剖.如果学生人数较多,对教师的心神精力是一个考验.而使用本工具,因为每一关键步骤都有提示,比照源代码,其运行逻辑通常立即就可以抓住.

批改作业时只阅读程序而不运行,细节错误很难发现.只看运行最终结果,虽能发现有错,但要找到问题所在也很困难.而使用本工具,只要对输出的信息有合适安排,那么定位错误位置,找出症结所在就会容易很多.

当然,在此基础上还可以进一步开展工作,比如对处理过程、运行结果添加自动评分功能,对代码实现简单的数据流、控制流分析以更清晰显现程序逻辑等,这都有待于今后继续努力.

参考文献(References):

[1] Tim Lindholm, Frank Yellin. The Ja Virtual Machine Specification Ja SE 11 Edition[M] Addison-Wesley Professional,2018.8

[2] Eric Bruneton. A 4.0 A Ja bytecode engineering library[EB/OL].http://www.ow2.org/

[3] objectweb.org. a 7.0 API[EB/OL]. http://www.ow2.org/

[4] James Gosling, Bill Joy. The Ja LanguageSpecificationJa SE 11 Edition [M] Addison-Wesley Professional 2018.8

上文总结,此文为关于作业方面的大学硕士和本科毕业论文以及A和作业和辅助和批阅和工具相关作业论文开题报告范文和职称论文写作参考文献资料.

作业引用文献:

[1] 经典初中数学作业论文选题 初中数学作业论文题目怎样定
[2] 比较好写的小学英语作业论文题目 小学英语作业论文标题如何定
[3] 小学语文作业方面论文题目 小学语文作业论文题目选什么比较好
《作业论文范文 作业有关论文参考文献范文5000字》word下载【免费】
作业相关论文范文资料