深度学习策略下缓慢循环异味检测方法

2024-02-27 09:02边奕心李禹齐张子恒尹启天李文渊
小型微型计算机系统 2024年2期
关键词:异味应用程序分类器

边奕心,李禹齐,张子恒,赵 松,尹启天,李文渊

(哈尔滨师范大学 计算机科学与信息工程学院,哈尔滨 150025)

0 引 言

代码异味(Code Smell)又被称为代码坏味道,是由Martin Fowler于1999年提出的,表示存在于程序中的结构不良的代码段[1].代码异味对软件的可理解性和可维护性产生诸多负面影响.这种由Martin Fowler提出的异味也被称为面向对象代码异味[2].随着新技术的不断涌现和代码异味研究的持续发展,代码异味不再局限于表示面向对象代码中的潜在问题,已经拓展到众多领域[3],如安卓/IOS应用程序[4,5]、测试[6]及SQL[7]等代码异味.随着科学技术的迅猛发展,Android应用程序由于其开放性和易用性,被广泛应用到人们的日常生活中.研究表明,代码异味不仅仅存在于传统的桌面应用程序中,也存在于Android应用程序中[2].与传统桌面应用程序相比,Android应用程序没有主函数,程序执行入口是由Activity所提供的;Android应用程序没有J2SE、API、Swing和JavaFX,而且Android应用程序上的GUI是通过XML来声明的等.以上差异导致Android应用程序中不仅存在传统面向对象代码异味,还存在着Android特有的代码异味(Android-specific smells).2014年Reimann[4]等人提出了Android特有代码异味并给出了详细的异味列表.这种异味的存在对Android应用程序产生了诸多负面影响,比如能耗、安全性、稳定性、内存和启用时间等,极大降低了用户体验,不利于Android应用程序的维护和演化[8].Manman等人的研究表明[9],可以使用传统的桌面应用程序中代码异味检测工具检测Android应用程序中的面向对象代码异味.但是,研究表明[10],由于Android应用程序与传统面向对象应用程序的结构不同,因此,传统检测工具不能检测Android特有代码异味.

Android特有代码异味共包括30种味道,本文针对其中一种异味,缓慢循环,展开深入研究,研究其自动化检测方法.缓慢循环是Android应用程序中的传统for循环语句.在Android应用程序中,for-each循环语句比传统for循环语句的处理速度快,因此,传统for循环语句被认为是代码异味[4].目前检测Android特有代码异味效果最好的工具是DAAP[10],该工具采用传统检测工具普遍使用的程序静态分析技术,定义启发式检测规则,通过遍历抽象语法树,实现异味的检测.

近几年,深度学习在自然语言处理和图像分类等领域成绩卓著.软件工程领域的很多学者尝试使用不同的深度学习方法或者机器学习技术解决代码异味问题,取得了良好的效果[8-13].然而,已有研究都关注面向对象的代码异味研究,还没有使用深度学习方法检测Android特有代码异味的相关研究.因此,本文使用深度学习方法检测缓慢循环这种Android特有异味.此外,为了获取模型所需的大量标签数据,本文提出一种基于Android开源项目构造正负样本的方法,并实现工具ASSD,实现样本的自动生成和标注.

1 相关工作

1.1 Android特有代码异味

Android特有代码异味,也被称为安卓代码坏味[3],是Android应用程序中存在设计缺陷的代码段[2].2014年Reimann等人[4]提出“质量味道”的概念,用以表示Android应用程序中影响软件质量的代码结构,并具体列出了30种质量味道.这些质量味道被后续的研究称为Android特有代码异味[2,3,8,14].这种异味对Android应用程序产生了诸多负面影响,比如能耗、安全性、稳定性、内存和启用时间等,不利于Android应用程序的维护和演化[15].根据Manman等人的研究[9],传统检测工具不能检测Android特有代码异味,因此,自2014年之后,学者们提出不同的方法检测Android特有代码异味.Palomba等人[2]提出将代码度量与简单文本比较相结合的方法检测15种Android代码异味,并实现了工具aDoctor.尽管aDoctor是免费的软件,但其源代码并不公开,使用者不能在其基础上根据需要进行功能扩展.Iannone等人[17]将aDoctor进展扩展,对5种与能量相关的Android特有代码异味进行重构.为了检测更多种类的Android代码异味,Rasool等人[7]定义启发式检测规则,结合代码度量对25种异味进行检测,并实现工具DAAP.工具DAAP在检测异味种类与准确度方面都优于aDoctor,并公开源代码,便于后续研究者的使用和功能扩展.

1.2 缓慢循环异味

缓慢循环(Slow Loop,简称SL)是Reimann等人[3]提出的30种Android特有代码异味的一种,同时也是存在于程序中数量较多的一种味道(仅次于忽略成员的方法味道)[8].SL是Android应用程序中的传统for循环语句.由于这种循环语句处理数据的速度比for-each循环语句慢,所以,在Android应用程序中,被认为是异味.SL异味的重构方式是通过迭代器模式来实现循环可以将其转变为for-each循环.

目前主要采用传统的静态程序分析方法检测SL异味.Nucci等人[2]认为传统的for循环处理数据速度较慢,因此Android开发者应该尽量使用增强版本的循环来提高应用程序的效率,使用aDoctor检测器将使用传统for循环的所有方法识别为SL异味[2].Rasool等人[10]根据代码异味的不同特征与定义选择不同的度量,以预设阈值的方式为各个异味制定不同的检测规则,来检测异味SL,并实现了工具DAAP.通过实际运行程序,本文发现传统的静态程序分析检测方法存在两个问题:首先,根据检测规则,只要是存在传统for循环的方法,都被认为是异味,而实际中并不是所有的传统for循环都适合重构为for-each循环,因此,误检率较高.其次,传统检测方法只能定位到异味所在的类,而一个类中含有多个方法,使用者不能确定是哪个方法包含异味,还需要手动挑选.

1.3 基于机器学习的代码异味检测方法

随着机器学习技术的迅速发展,及以Github开源代码库为支撑的“Big Code”的出现[18],软件工程领域的学者们尝试使用机器学习或者深度学习方法检测代码异味.Amorim等人[19]在4个中等规模的开源项目中证实了Kreimer[20]最初提出使用决策树在两个小型软件系统上检测长方法异味,发现这种预测模型可以获得较高的精度.Khomh等人[8,21]提出使用贝叶斯信念网络来检测开源程序上的代码异味实例.Fontana等人[11]使用一套16种机器学习模型来检测4种代码异味,在此研究中,所有的机器学习者都在交叉项目场景中获得了高性能,其中J48和随机森林分类器获得了最高的精度.以上研究所用的特征集都是传统的代码度量.

随着深度学习在各个领域的成功应用,近年来,很多学者将深度学习技术引入了代码异味检测研究中.刘辉等人[13]提出一种基于卷积神经网络的方法检测上帝类异味,检测结果获得了大幅度提升.在此基础上,他们将卷积神经网络和长短时记忆网络相结合,检测4种代码异味[22].以上两项研究在训练模型时,不仅使用了传统的代码度量,还结合了代码文本信息(变量的标识符).Sharma等人[23]分别使用卷积神经网络、循环神经网络和自编码器对4种代码异味进行检测.Sharma认为使用代码度量会导致模型学习过程受限于度量信息,无法获得度量以外的源代码特征,同时,即便使用相同的度量,因为阈值的不同,导致不同检测方法的检测结果存在较大的差异.另外,度量选取的主观性也会影响检测效果[23].因此,Sharma没有使用任何传统的度量信息,而是使用程序文本信息作为模型的输入.Sharma使用的程序文本信息不同于刘辉[22]使用的文本信息,Sharma将源代码转换为整数,以数字向量形式表示程序的文本信息,这种文本信息涵盖了程序的全部信息.本文借鉴这种方法,获取源代码文本特征.

综上所述,已有使用深度学习或者机器学习检测代码异味的方法都只关注面向对象代码异味.还没有使用深度学习检测Android特有代码异味的相关研究.因此,为了弥补传统基于程序静态分析的检测方法的不足,提高Android特有代码异味的检测精度,本文提出一种基于深度学习的SL检测方法.此外,为了准确快速获得学习模型所需的大量标签数据,本文提出一个基于Android项目自动生成正负样本集的方法并实现工具ASSD,自动生成学习模型需要的大量标签数据.

2 缓慢循环检测方法

2.1 方法概述

本文提出的基于深度学习的SL检测方法如图1所示.首先,以开源的Android应用程序作为实验所需的代码语料库.使用工具ASSD对语料库中的程序进行SL异味检测,自动将Java源程序中的每个正样本(含有SL的代码段)和负样本(没有SL的代码段)提取出来生成对应的文件,生成标签样本集,即正样本集合与负样本集合.接着使用工具Tokenizer将标签样本集中的源代码转换为整数,以数字向量的形式表示程序的文本信息,作为模型输入的特征集.深度神经网络分类器的预期输出为样本的标签(即是否为SL异味).经过50次训练验证后,最终获得被训练好的分类器.然后通过测试集测试分类器性能,并给出代码异味的检测结果.后续章节将依次介绍每个关键步骤的具体细节.

图1 基于深度学习的SL检测方法概图Fig.1 Overview of SL detection method based on deep learning

2.2 数据集构建

本节详细介绍生成标签数据集的过程及使用的工具.

2.2.1 实验对象获取

在开源代码库AndroZooOpen[24]中下载Android应用程序,作为备选的代码语料库.AndroZooOpen是一个公开的Android应用程序集合,包括Gitbub、F-Droid和Google Play在内的多个数据来源.AndroZooOpen目前包含76466个由不同语言开发的Android 应用程序.本文选择主要由Java语言开发的Android应用程序,因为Java 是目前移动应用软件开发的主流语言之一,而且目前Android特有代码异味的检测工具只能检测由Java语言开发的应用程序.

首先,从AndroZooOpen下载110个开源Android应用程序.然后,使用工具RepoReapers去除低质量的Android应用程序.RepoReapers可以从8个方面对AndroZooOpen中的程序质量进行评分(分别是体系结构、社区、持续集成、文件、提交历史、许可证、问题和单元测试).如果待选应用程序在8个方面的评分均大于零,本文认为该程序是合适的.按照这些标准经过筛选,最终确定70个Android应用程序作为代码语料库,这70个应用程序共有747264行代码,9574个类和87320个方法.

2.2.2 样本生成

在深度学习的传统应用领域,研究者可以免费获得大量带有标签的图像数据集,用以构建模型的训练集.而在代码异味检测研究中,目前还没有类似的资源可供研究者使用[13].为了解决这个问题,刘辉团队和Sharma团队利用已有代码异味检测工具的输出结果,构建模型的训练集.本文借鉴这种方法,使用工具ASSD检测异味SL并自动生成正、负样本集.

本文使用的工具ASSD是在检测工具DAAP的基础上对其功能进行扩展,实现从异味检测到样本生成自动完成(它没有改变DAAP的异味检测规则,为区别于原DAAP工具,本文将改进后的工具称为ASSD).待分析的Java源代码经过JavaParser进行解析生成抽象语法树,然后,根据检测规则遍历语法树,输出异味.图2中虚线部分所示为DAAP工具,虚线外的功能是本文扩展的功能.

图2 自动生成正负样本的流程图Fig.2 Flowchart of automatic generating of positive and negative sample sets

DAAP是现有Android特有代码异味检测工具中检测异味种类最多、效果最好的工具,可以检测包括SL在内的25种Android特有代码异味.Rasool[10]等人使用DAAP检测4种应用程序中SL异味的F1值,平均可以达到97.25%.同时DAAP是完全开源的工具,使用者不仅可以免费获得,而且可以在其基础上进行功能扩展,以满足不同的需求.因此,本文首选DAAP检测SL异味.但是,DAAP中检测SL规则是将检测到的所有传统for循环都认为SL.但在实际中,并不是所有传统的for循环都适合改写成for-each,这种不适合改动的传统for循环语句并不属于SL异味.此外,由于DAAP的检测结果只能定位到类级别,不能定位到SL异味存在的语句,不利于后续重构的操作.基于以上原因,本文在DAAP的基础上,对其功能进行扩展,开发了工具ASSD.ASSD不仅可以将检测出的SL异味定位到所在的代码段,而且还可以自动生成正负样本集合.因此,ASSD从异味检测到样本生成完全自动完成,从而获取到充足的缓慢循环异味标签样本集.算法1所示为正负样本自动生成的过程,主要通过文件操作将检测结果输出,生成正负样本集合.自动生成正负样本步骤如下:

1)分别创建存储正样本的文件目录smellyFile和存储负样本的文件目录nonsmellyFile(对应算法1第2~5行、第12~15行).

2)遍历smellySets,将每一个传统for 循环语句写入一个.java文件,生成正样本集合(对应算法1第6~11行).

3)遍历nonsmellySets,将每一个for-each 语句写入一个.java文件,生成负样本集合(对应算法1第16~20行).

算法1.正负样本自动生成

Input:smellySets,nonsmellySets

Output:smellyFiles,nonsmellyFiles

1.String folderPath=DRIVE+"\AndroidApp"

2.File file=new File(folderPath+"\"+smellyName)

3.if !file.exists()then

4. file.mkdirs()

5.endif

6.Stringfilepath=folderPath+"\"+smellName+"\"+filename+".java"

7. BufferedWriter bw=new BufferedWriter(new FileWriter(filepath))

8.foreach forStmt in smellySetsdo

9. bw.write(forStmt);

10.endfor

11.bw.close()

12.Filefile_1=newFile(folderPath+"\"+nonsmellySets)

13.if!file_1.exists()then

14. file_1.mkdirs()

15.endif

16.Stringfilepath=folderPath+"\Not_"+smellName+"\"+filename+".java"

17. BufferedWriter bw_1=new BufferedWriter(new FileWriter(filepath))

18.foreach forEachStmt in nonsmellySetsdo

19. bw_1.write(forEachStmt)

20.endfor

21.bw_1.close()

2.3 特征提取

异味检测工具ASSD的输出结果是程序代码,而深度学习模型需要的输入是数字向量,因此,为了使用深度学习算法进行异味检测,需要将程序代码转换成数字向量.Sharma等人[23]认为,只使用代码度量作为特征集,模型受限于度量信息,无法学习到度量之外的程序特征.因此,Sharma使用工具Tokenizer将源代码转换为整数,用数字向量表示程序文本信息,并将这些数字向量作为模型输入的特征集.Tokenizer是一种开源工具,它提供了可以将源代码转换为整数的功能,其中不同的代码信息匹配不同的整数,图3所示为一个SL异味方法的java源代码由Tokenizer转化成相对应的整数.

图3 Tokenizer标记SL示例Fig.3 Tokens generated by Tokenizer for SL example

由于缓慢循环异味存在于特殊的代码段,与所在类或方法前后无密切联系,而且作为深度神经网络模型输入时,全部代码文本过于冗长可能导致维度爆炸,所以需要对代码文本进行一部分的预处理操作.本文使用工具ASSD直接从代码文本中提取出与缓慢循环代码异味相关的代码段作为特征集合,去除与学习任务无关的特征,以便降低模型构建的难度.此外,在对Tokernizer提取的代码文本特征统计和分析中发现,80%的方法中不会超过66个元素.在本文中将模型输入的单个样本中的代码文本特征个数固定在66个,即只针对被检测样本中的66个元素进行预处理,将样本中元素少于66个以全零向量来做补零扩展.

2.4 深度神经网络分类器

本文使用两种常用的深度神经网络模型进行异味检测,分别为卷积神经网络模型和循环神经网络模型,这两种模型既是经典的深度神经网络模型,也是在异味检测中使用频率最高的模型[20].本节详细介绍这两种模型的结构.

2.4.1 卷积神经网络模型

卷积神经网络(Convolutional Neural Networks,CNN)是深度学习的代表算法之一,是一种包含卷积计算的前馈神经网络.本文使用的CNN模型结构如图4所示,表1为CNN模型结构各层数选定的参数值.首先,将文本信息转换成数值信息,然后,输入到嵌入层(Embedding),进行重新编码等操作.为了避免输入数组中填充零产生的噪声,在嵌入层中将mask_zero参数设置为True,只考虑输入数据的有意义部分.接着,进入到卷积层(Convolution 1D)和最大池化层(Max pooling),卷积层根据指定的滤波器(filter)和内核参数进行卷积运算,相应地计算到下一层的网络权重,最大池化层降低了矩阵的维度进而减小计算量和消除了数据噪音.最后一个池化层的输出连接到Dropout层,根据相应的概率删除一部分的神经元,然后开始训练,更新没有被删除的神经元以及权重的参数将其保留,以防止过度拟合等问题.该层的脱落率设置为0.5,表示要被拿掉的神经元是随机选择的,概率为0.5.Dropout层的输出被输入到Flatten层把多维的数据一维化,最后输入到第一个全连接层(Dense),本全连接层激活函数为relu函数输出一组包含800个输出的数据.再由一层全连接层映射到最终的Sigmoid输出层,输出层激活函数为sigmoid函数,输出维度为1,以便根据所调查的异味来预测一个实例是否属于该异味.最终选取的模型损失函数(loss function)为binary_crossentropy函数,优化器(optimizer)为RMSProp,迭代次数(epoch)为50次.

表1 CNN模型层数参数值Table 1 CNN model layer parameter value

图4 基于CNN的神经网络分类器Fig.4 Classifier based on CNN model

2.4.2 循环神经网络模型

循环神经网络(Recurrant Neural Networks,RNN)也是深度学习的代表算法之一,用以处理序列数据.如图5所示为检测SL异味的RNN模型的体系结构图,表2为RNN模型结构各层数选定的参数值,该结构受到自然语言建模中RNN模型的启发,由一个嵌入层、一个长短时记忆网络(Long Short-Term Memory,简称LSTM)、Flatten层和全连接层组成.同CNN模型类似,以数值信息作为输入经过嵌入层进入到LSTM层.原始的RNN在训练中,随着训练时间的加长以及网络层数的增多,容易出现梯度爆炸或梯度消失的问题,导致无法处理较长序列数据,从而无法获取长距离数据的信息,为了解决这些问题,本文选用了长短时记忆网络.将LSTM层的输出维度设置成128,经过Flatten层输入到3个全连接层,前两层激活函数为relu函数,最后输出层激活函数为sigmoid函数,最终输出一维向量.与CNN模型一样(选取的模型损失函数(loss function)为binary_crossentropy函数,优化器(optimizer)为RMSProp,迭代次数(epoch)为50次).

表2 RNN模型层数参数值Table 2 RNN model layer parameter value

图5 基于RNN的深度神经网络分类器Fig.5 Classifier based on RNN model

3 实验验证

本章实验环境如下:操作系统是windows 10,处理器是Intel Core i7-7500U,内存是12GB,实验工具分别为为PyCharm、IntelliJ IDEA和weka,编程语言为Python和Java.此外,实验相关工具(ASSD)和 数 据 已 上 传 至https://github.com/lyqlq/SLDetection.

3.1 研究问题

本文主要围绕以下问题进行实验研究:

在实验中,本文提出了4个研究问题(Research question,简称RQ),通过回答这些问题对本文所提方法进行评估.

RQ1:使用深度学习的方法是否能准确有效检测出缓慢循环异味?如果可以检测,哪种深度学习模型的检测效果更好?

RQ2:使用相同数据集作为模型输入,基于深度学习的检测方法是否优于基于机器学习的检测方法?

RQ3:基于深度学习的检测方法是否优于现有的基于程序静态分析的检测方法?

RQ4:本文提出的方法用于生成训练深度神经网络所需的数据集需要消耗多少时间?用于训练深度神经网络模型又需要消耗多少时间?

RQ1关注深度神经网络分类器的检测异味的能力和差异性.在相同输入的前提下,使用查准率、查全率和F1值3个指标来评估不同分类器的有效性.对两种神经网络分类器的检测效果进行比较.

RQ2关注检测Android特有代码异味时,深度神经网络分类器和机器学习分类器的差异性.以各个分类器在输入相同数据集的情况下检测出的最优F1值作为衡量指标进行比较.

RQ3关注的是本文方法与现有基于静态程序分析的检测方法检测SL异味上的差异.为了回答这个问题,本文选择DAAP作为评估阶段的对比实验对象.之所以选择DAAP,是因为DAAP是目前检测Android特有代码异味种类最多、检测准确度最好的工具.

RQ4关注本文所提方法时间性能的具体表现.针对数据集上70个开源程序,记录了在整个检测SL代码异味上的耗时情况.可以根据所提出方法在建立模型和训练数据中所需花费的时间成本,探讨基于深度学习方法在时间性能上的具体表现.

3.2 模型评价指标

本章使用查准率(Precision)、查全率(Recall)和 F1 值(F1-score)对不同分类器进行评估,它们的计算方法如公式(1)~公式(3)所示:

(1)

(2)

(3)

其中,公式中的TP(True Positive)为被检测为正的正样数,表示实际上阳性样本的数量;FP(False Positive)为被检测为正的负样本数,表示实际上是阴性样本但被判定为阳性样本的样本数量;FN(False Negative)为被检测为负的正样本数,表示实际上是阳性样本但被判定为阴性样本的样本数量;TN(True Negative)表示实际上是负样本的样本数量,也被判定为阴性样本.

3.3 实验设计

实验1.为了回答 RQ1,以2.2节构建的程序文本数据集作为CNN和RNN模型的输入,以相同的正负样本训练模型.首先,将数据集按7:3的比例分成训练数据和测试数据,其中,使用测试数据的判别效果来估计模型在实际使用时的泛化能力,然后,将训练数据再按8:2的比例划分为训练集和验证集,根据验证集上的性能来进行模型选择和调参,进行50次训练验证和1次测试得到检测结果.最后,使用查准率、查全率、F1 值对相同特征输入的2种神经网络分类器的检测效果进行比较.

实验2.为了回答RQ2,选取相同的数据集作为模型的输入.深度神经分类器的检测方法同实验一.首先,使用工具weka完成基于机器学习的代码异味检测,其中,参考Fontana等人[11]的研究结果,选取其中性能最好的4种机器学习模型,即随机森林(RF)、J48、JRip、朴素贝叶斯(NB),作为本次实验的基础模型,然后,使用十折交叉验证对模型进行验证.最后,以F1值作为标准,对比出不同检测方法的差异性.

实验3.为了回答RQ3,首先,从Palomba等人[11]提出的一个开源Android应用程序数据集(共60个Android应用程序)中选取10个开源Android应用程序作为测试程序.这10个应用程序与模型训练阶段的70个应用程序没有重叠.表3所示为使用的10个开源Android项目的详细信息.然后,将新的测试集输入已训练好的神经网络分类器中进行SL异味检测.此外,为了进行对比,本文使用检测工具DAAP对这10个应用程序进行SL异味检测.为准确评价该工具的检测结果,本文以Palomba等人[11]提出的SL异味目录作为参考,使用查准率、查全率和F1值对检测方法的检测效果进行比较.

表3 测试集所用的10个Android应用程序Table 3 10 Android apps used in the test set

实验4.为了回答RQ4,本文在普通配置的笔记本电脑(12GB RAM,Intel Core CPU i7-7500)上运行实验的全部流程,并记录了耗时情况(以分钟为单位),对所提出方法的时间性能进行分析.

3.4 实验结果分析

RQ1:表4所示为两种神经网络分类器在相同特征输入的检测结果.

表4 不同模型在相同特征下的SL检测结果Table 4 Results on SL detection of different models with the same features

如表4所示,两种神经网络模型的查准率、查全率和F1值都较高,因此使用深度神经网络检测缓慢循环异味是可行的,且检测效果很好.图6所示为随着迭代次数(Epochs)的增加,两种模型的3项性能指标分别在训练集和验证集上的变化过程.其中,左图(a)为CNN模型3个指标随着迭代次数增加的变化过程,右图(b)为RNN模型3个指标随着迭代次数增加的变化过程.从曲线变化趋势可以看出,随着迭代次数的增加,两种模型的3项指标在训练集和验证集都较高且差别不大,表明两种模型把数据的规律拟合出来了,能够很好的检测代码异味.

图6 CNN和RNN模型的3个性能指标随着迭代次数增加的变化过程Fig.6 Change process of the three performance metrics of the CNN and the RNN model as the epoch increases

此外,如表4所示,3项性能指标数据,CNN模型的检测效果均略优于RNN模型.在深度学习的传统应用领域,由于RNN模型更擅长处理文本,因此在自然语言处理领域有着广泛的应用.而程序源代码与自然语言文本有诸多相似之处,因此可以认为,在检测代码异味时,RNN模型的检测效果应优于CNN模型.但Sharma等人认为[18],程序源代码与自然语言文本也有很多不同之处,这些差异可能导致擅长处理自然语言文本的方法在处理程序源代码时表现不佳.同时他们的研究结果表明[18],在检测面向对象代码异味时,RNN模型的检测效果因味道的不同而发生变化,不一定比CNN检测效果好.根据表4结果,在检测缓慢循环这种Android代码异味时,需要识别类中的传统for循环语句,在识别能力上,CNN与RNN模型都较强,但RNN模型略逊色于CNN模型.

RQ2:表5所示为深度神经网络分类器和机器学习分类器在输入相同特征下的检测结果.

表5 不同分类器的性能比较Table 5 Performance comparison of different classifiers

如表5所示,分类器对SL的检测性能综合排名为:卷积神经网络(CNN)>循环神经网络(RNN)>随机森林(RF)>JRip>J48>朴素贝叶斯(NB).本文所使用的深度神经网络模型检测结果普遍优于机器学习模型,相对于检测效果最好的随机森林,CNN模型的检测效果有所提升,F1值平均提高了9.43%=(95.65%~86.22%).

RQ3:对表1中的10个Android应用程序,表6分别列出了两种深度神经网络分类器与基于静态程序分析检测工具DAAP的检测结果.

表6 不同检测方法的结果比较Table 6 Comparison of the results of different detection methods

如表6所示,深度神经网络分类器对SL异味的检测效果在查准率、查全率和F1值上均优于DAAP.其中,检测效果提升最为明显的是CNN模型,F1值平均提高了28.7%=(98.59%~69.89%).

RQ4:由于篇幅限制,表7仅列出了其中10个Android应用程序生成训练集所花费的时间(以分钟为单位),全部 70 个应用程序所消耗时间的详细信息请已上传至如第3节所示的网址.可以看出,收集样本数据耗时较多,为了从70个Android应用程序中提取训练集数据,累计花费了1061分钟(约17.7小时),平均每个项目需要15.16分钟.其中,耗时最多的项目是AndroidChromium(类数=1007、方法数=1183、代码行数=89051,消耗149分钟),耗时最少的项目是xCalc(类数=33、方法数=201、代码行数=1548,耗时9分钟).

表7 生成训练集数据消耗时间Table 7 Time of train set data genertion

与耗费17个多小时的训练集生成过程相比,深度神经网络分类器在70个开源项目上的训练过程消耗时间分别为:卷积神经网络为22.7s,循环神经网络为223.6s.因为自动生成训练集数据是可以提前实现的,所以并不需要在每次进行缓慢循环异味检测时生成训练集.同时,CNN模型仅考虑当前输入,而RNN模型考虑当前输入以及先前接收的输入,故从时间上对比CNN模型在数据集训练上所需要的时间更少.

4 总 结

本文使用深度学习方法检测缓慢循环这种Android特有代码异味.首先,分析大量源码,从中提取出与缓慢循环相关特征,并将源代码转换成数字信息作为模型输入的特征集,然后,使用CNN和RNN两种深度神经网络分类器进行检测.接着,在保证模型输入的特征集相同的情况下,对比4种机器学习模型的检测效果.实验结果表明,基于深度学习的检测方法不仅可以检测Android特有代码异味,而且检测效果优于基于机器学习的方法和基于程序静态分析的检测方法.此外,为了快速准确生成有监督机器学习模型所需的大量训练集和测试集,本文提出了一种利用开源Android应用程序自动构建正负样本的工具的方法,并实现工具ASSD,实现从异味检测到样本生成自动完成.

目前,本文只对缓慢循环这一种Android特有代码异味进行检测,Reimann等人的Android异味列表中共包括30种味道,在后续的研究中,将在本文方法的基础上,对更多种类的Android特有代码异味进行检测.目的是探索深度学习模型检测Android代码异味时,针对不同的异味,检测效果是否有差异.同时研究异味的重构方法,最终目的是提高软件的质量.

猜你喜欢
异味应用程序分类器
删除Win10中自带的应用程序
基于4G技术的VOCs及异味检测系统
谷歌禁止加密货币应用程序
BP-GA光照分类器在车道线识别中的应用
用这些告别异味吧!夏天就要清清爽爽过!
PIC-408系列采用育种技术控制公猪异味
加权空-谱与最近邻分类器相结合的高光谱图像分类
结合模糊(C+P)均值聚类和SP-V-支持向量机的TSK分类器
基于LLE降维和BP_Adaboost分类器的GIS局部放电模式识别
去除鞋柜异味等