当前位置:首页 » 安卓系统 » android静态分析

android静态分析

发布时间: 2022-11-27 02:56:16

‘壹’ 手机调试Android程序出异常时不打印堆栈信息

打印堆栈是调试的常用方法,一般在系统异常时,我们可以将异常情况下的堆栈打印出来,这样十分方便错误查找。实际上还有另外一个非常有用的功能:分析代码的行为。android代码太过庞大复杂了,完全的静态分析经常是无从下手,因此通过打印堆栈的动态分析也十分必要。

Android打印堆栈的方法,简单归类一下
1. zygote的堆栈mp
实际上这个可以同时mp java线程及native线程的堆栈,对于java线程,java堆栈和native堆栈都可以得到。
使用方法很简单,直接在adb shell或串口中输入:
[plain] view plain
kill -3 <pid>
输出的trace会保存在 /data/anr/traces.txt文件中。这个需要注意,如果没有 /data/anr/这个目录或/data/anr/traces.txt这个文件,需要手工创建一下,并设置好读写权限。
如果需要在代码中,更容易控制堆栈的输出时机,可以用以下命令获取zygote的core mp:
[java] view plain
Process.sendSignal(pid, Process.SIGNAL_QUIT);
原理和命令行是一样的。
不过需要注意两点:
adb shell可能会没有权限,需要root。
android 4.2中关闭了native thread的堆栈打印,详见 dalvik/vm/Thread.cpp的mpNativeThread方法:
[cpp] view plain
dvmPrintDebugMessage(target,
"\"%s\" sysTid=%d nice=%d sched=%d/%d cgrp=%s\n",
name, tid, getpriority(PRIO_PROCESS, tid),
schedStats.policy, schedStats.priority, schedStats.group);
mpSchedStat(target, tid);
// Temporarily disabled collecting native stacks from non-Dalvik
// threads because sometimes they misbehave.
//dvmDumpNativeStack(target, tid);
Native堆栈的打印被关掉了!不过对于大多数情况,可以直接将这个注释打开。

2. debuggerd的堆栈mp
debuggerd是android的一个daemon进程,负责在进程异常出错时,将进程的运行时信息mp出来供分析。debuggerd生 成的coremp数据是以文本形式呈现,被保存在 /data/tombstone/ 目录下(名字取的也很形象,tombstone是墓碑的意思),共可保存10个文件,当超过10个时,会覆盖重写最早生成的文件。从4.2版本开 始,debuggerd同时也是一个实用工具:可以在不中断进程执行的情况下打印当前进程的native堆栈。使用方法是:
[plain] view plain
debuggerd -b <pid>
这可以协助我们分析进程执行行为,但最最有用的地方是:它可以非常简单的定位到native进程中锁死或错误逻辑引起的死循环的代码位置。

3. java代码中打印堆栈
Java代码打印堆栈比较简单, 堆栈信息获取和输出,都可以通过Throwable类的方法实现。目前通用的做法是在java进程出现需要注意的异常时,打印堆栈,然后再决定退出或挽救。通常的方法是使用exception的printStackTrace()方法:
[java] view plain
try {
...
} catch (RemoteException e) {
e.printStackTrace();
...
}
当然也可以只打印堆栈不退出,这样就比较方便分析代码的动态运行情况。Java代码中插入堆栈打印的方法如下:
[java] view plain
Log.d(TAG,Log.getStackTraceString(new Throwable()));

4. C++代码中打印堆栈
C++也是支持异常处理的,异常处理库中,已经包含了获取backtrace的接口,Android也是利用这个接口来打印堆栈信息的。在Android的C++中,已经集成了一个工具类CallStack,在libutils.so中。使用方法:
[cpp] view plain
#include <utils/CallStack.h>
...
CallStack stack;
stack.update();
stack.mp();
使用方式比较简单。目前Andoid4.2版本已经将相关信息解析的很到位,符号表查找,demangle,偏移位置校正都做好了。
[plain] view plain

5. C代码中打印堆栈
C代码,尤其是底层C库,想要看到调用的堆栈信息,还是比较麻烦的。 CallStack肯定是不能用,一是因为其实C++写的,需要重新封装才能在C中使用,二是底层库反调上层库的函数,会造成链接器循环依赖而无法链接。 不过也不是没有办法,可以通过android工具类CallStack实现中使用的unwind调用及符号解析函数来处理。
这里需要注意的是,为解决链接问题,最好使用dlopen方式,查找需要用到的接口再直接调用,这样会比较简单。如下为相关的实现代码,只需要在要 打印的文件中插入此部分代码,然后调用getCallStack()即可,无需包含太多的头文件和修改Android.mk文件:
[cpp] view plain
#define MAX_DEPTH 31
#define MAX_BACKTRACE_LINE_LENGTH 800
#define PATH "/system/lib/libcorkscrew.so"

typedef ssize_t (*unwindFn)(backtrace_frame_t*, size_t, size_t);
typedef void (*unwindSymbFn)(const backtrace_frame_t*, size_t, backtrace_symbol_t*);
typedef void (*unwindSymbFreeFn)(backtrace_symbol_t*, size_t);

static void *gHandle = NULL;

static int getCallStack(void){
ssize_t i = 0;
ssize_t result = 0;
ssize_t count;
backtrace_frame_t mStack[MAX_DEPTH];
backtrace_symbol_t symbols[MAX_DEPTH];

unwindFn unwind_backtrace = NULL;
unwindSymbFn get_backtrace_symbols = NULL;
unwindSymbFreeFn free_backtrace_symbols = NULL;

// open the so.
if(gHandle == NULL) gHandle = dlopen(PATH, RTLD_NOW);

// get the interface for unwind and symbol analyse
if(gHandle != NULL) unwind_backtrace = (unwindFn)dlsym(gHandle, "unwind_backtrace");
if(gHandle != NULL) get_backtrace_symbols = (unwindSymbFn)dlsym(gHandle, "get_backtrace_symbols");
if(gHandle != NULL) free_backtrace_symbols = (unwindSymbFreeFn)dlsym(gHandle, "free_backtrace_symbols");

if(!gHandle ||!unwind_backtrace ||!get_backtrace_symbols || !free_backtrace_symbols ){
ALOGE("Error! cannot get unwind info: handle:%p %p %p %p",
gHandle, unwind_backtrace, get_backtrace_symbols, free_backtrace_symbols );
return result;
}

count= unwind_backtrace(mStack, 1, MAX_DEPTH);
get_backtrace_symbols(mStack, count, symbols);

for (i = 0; i < count; i++) {
char line[MAX_BACKTRACE_LINE_LENGTH];

const char* mapName = symbols[i].map_name ? symbols[i].map_name : "<unknown>";
const char* symbolName =symbols[i].demangled_name ? symbols[i].demangled_name : symbols[i].symbol_name;
size_t fieldWidth = (MAX_BACKTRACE_LINE_LENGTH - 80) / 2;

if (symbolName) {
uint32_t pc_offset = symbols[i].relative_pc - symbols[i].relative_symbol_addr;
if (pc_offset) {
snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s (%.*s+%u)",
i, symbols[i].relative_pc, fieldWidth, mapName,
fieldWidth, symbolName, pc_offset);
} else {
snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s (%.*s)",
i, symbols[i].relative_pc, fieldWidth, mapName,
fieldWidth, symbolName);
}
} else {
snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s",
i, symbols[i].relative_pc, fieldWidth, mapName);
}

ALOGD("%s", line);
}

free_backtrace_symbols(symbols, count);

return result;
}
对sched_policy.c的堆栈调用分析如下,注意具体是否要打印,在哪里打印,还可以通过pid、uid、property等来控制一下,这样就不会被淹死在trace的汪洋大海中。
[plain] view plain
D/SchedPolicy( 1350): #00 pc 0000676c /system/lib/libcutils.so
D/SchedPolicy( 1350): #01 pc 00006b3a /system/lib/libcutils.so (set_sched_policy+49)
D/SchedPolicy( 1350): #02 pc 00010e82 /system/lib/libutils.so (androidSetThreadPriority+61)
D/SchedPolicy( 1350): #03 pc 00068104 /system/lib/libandroid_runtime.so (android_os_Process_setThreadPriority(_JNIEnv*, _jobject*, int, int)+7)
D/SchedPolicy( 1350): #04 pc 0001e510 /system/lib/libdvm.so (dvmPlatformInvoke+112)
D/SchedPolicy( 1350): #05 pc 0004d6aa /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+417)
D/SchedPolicy( 1350): #06 pc 00027920 /system/lib/libdvm.so
D/SchedPolicy( 1350): #07 pc 0002b7fc /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
D/SchedPolicy( 1350): #08 pc 00060c30 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+271)
D/SchedPolicy( 1350): #09 pc 0004cd34 /system/lib/libdvm.so
D/SchedPolicy( 1350): #10 pc 00049382 /system/lib/libandroid_runtime.so
D/SchedPolicy( 1350): #11 pc 00065e52 /system/lib/libandroid_runtime.so
D/SchedPolicy( 1350): #12 pc 0001435e /system/lib/libbinder.so (android::BBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+57)
D/SchedPolicy( 1350): #13 pc 00016f5a /system/lib/libbinder.so (android::IPCThreadState::executeCommand(int)+513)
D/SchedPolicy( 1350): #14 pc 00017380 /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+183)
D/SchedPolicy( 1350): #15 pc 0001b160 /system/lib/libbinder.so
D/SchedPolicy( 1350): #16 pc 00011264 /system/lib/libutils.so (android::Thread::_threadLoop(void*)+111)
D/SchedPolicy( 1350): #17 pc 000469bc /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+63)
D/SchedPolicy( 1350): #18 pc 00010dca /system/lib/libutils.so
D/SchedPolicy( 1350): #19 pc 0000e3d8 /system/lib/libc.so (__thread_entry+72)
D/SchedPolicy( 1350): #20 pc 0000dac4 /system/lib/libc.so (pthread_create+160)
D/SchedPolicy( 1350): #00 pc 0000676c /system/lib/libcutils.so
D/SchedPolicy( 1350): #01 pc 00006b3a /system/lib/libcutils.so (set_sched_policy+49)
D/SchedPolicy( 1350): #02 pc 00016f26 /system/lib/libbinder.so (android::IPCThreadState::executeCommand(int)+461)
D/SchedPolicy( 1350): #03 pc 00017380 /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+183)
D/SchedPolicy( 1350): #04 pc 0001b160 /system/lib/libbinder.so
D/SchedPolicy( 1350): #05 pc 00011264 /system/lib/libutils.so (android::Thread::_threadLoop(void*)+111)
D/SchedPolicy( 1350): #06 pc 000469bc /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+63)
D/SchedPolicy( 1350): #07 pc 00010dca /system/lib/libutils.so
D/SchedPolicy( 1350): #08 pc 0000e3d8 /system/lib/libc.so (__thread_entry+72)
D/SchedPolicy( 1350): #09 pc 0000dac4 /system/lib/libc.so (pthread_create+160)

6. 其它堆栈信息查询

‘贰’ 电脑 文件 androidstudio1.3有什么用

1.项目设置在开始畅游AndroidStudio的世界之前,大家首先需要点击此处下载并进行安装。请注意,各位必须事先安装好JDK6或者更高版本。如果是在Windows系统环境下,先启动.exe文件、而后按照安装向导的指示一步步完成。如果大家使用的是OSX系统,则首先双击启动磁盘镜像,然后将AndroidStudio拖拽到自己的应用程序文件夹当中。在成功完成了以上各项步骤后,那么大家的开发环境应该已经得到了正确设置。接下来,我们可以准备好利用AndroidStudio创建自己的第一款Android应用程序了。当大家第一次启动AndroidStudio时,应该会看到该软件的欢迎屏幕,其中还提供一些选项、指导我们以此为起点迈出Android应用开发的第一步。在今天的教程中,我们将选择“NewProject(新项目)”选项。不过如果大家希望把Eclipse等其它环境中的现有项目转化为AndroidStudio项目,也可以选择“ImportProject(导入项目)”。AndroidStudio能够将Eclipse项目转换为AndroidStudio项目,并在项目中为用户提供必要的配置文件。如果大家在选项列表中点击了“OpenProject(打开项目)”,则可以开启已经利用AndroidStudio或者IntelliJIDEA创建出的项目。而选择“CheckoutfromVersionControl(版本控制检查)”的话,大家能够对处于版本控制之下的项目副本进行检查。通过这种方式,我们可以将现有项目作为基础、快速构建起新的针对性版本。由于我们需要从零开始,因此这里选择“新项目”。这时大家会看到一份选项列表,旨在对我们的新项目作出配置。在今天的教程中,我们将创建一款简单的应用程序,主要目的是为大家演示AndroidStudio中最为重要的一部分功能特性。相信大家也和我一样,会认为“HelloWorld”这个名称最适合本次开发出的新项目。正如大家在上面这幅截图中所看到,我把自己的应用程序命名为HelloWorld,并为其设定了模块名称。如果大家对IntelliJIDEA不太熟悉,可能不知道模块这东西到底是什么。模块实际上就是一个可以进行编译、运行、测试以及调试的独立功能单元。模块当中包含有源代码、编译脚本以及用于特定任务的其它组成部分。在创建新项目时,大家还可以为该项目设定软件包名称。在默认情况下,AndroidStudio会将项目包名称的最后一项元素设置为模块名称,但只要愿意、大家可以随意对其作出变更。其它设定内容还包括项目在设备上的保存位置、最低与推荐SDK、项目编译需要使用的SDK以及项目主题等等。大家也可以要求AndroidStudio创建一个Activity类、为其自定义一个启动图标,或者设定该项目是否支持GridLayout、Fragments、NavigationDrawer或者ActionBar等。这里我们不会为自己的应用程序创建自定义图标,因此大家可以取消“Createcustomlaunchicon(创建自定义启动图标)”项目前的勾选框。点击“Next(下一步)”继续进行其它项目设置步骤。由于我们在之前的步骤中勾选了“Createactivity(创建activity)”项目的勾选框,因此这里导航会要求大家对AndroidStudio将为我们创建的Activity类进行配置。由于我们将从空白Activity类开始进行配置,因此大家可以点击“Next”执行设置流程的下面几个步骤。这里大家需要对该Activity类、主布局以及片段布局进行命名。大家也可以设置导航类型,在今天的示例项目中我们将其设置为“None”。下面这幅截图显示的是我们的设置方案看起来是什么样子。在点击“Finish”之后,大家会看到如下图所示的AndroidStudio用户界面。其中窗口左侧为项目资源管理器,右侧则为工作区。在AndroidStudio中对项目进行设置之后,现在我们可以逐一查看AndroidStudio当中的各项关键功能。2.Android虚拟设备所谓Android虚拟设备——或者简称AVD——是一套模拟器配置方案,它允许大家设定出与实际情况相符的Android设备型号。这就让开发者在多种多样的设备平台上运行并测试应用程序变得更为轻松。在Android虚拟设备功能的支持下,大家可以为Android模拟器指定需要模拟的硬件与软件组合。创建Android虚拟设备的首选方式是通过AVDManager。大家可以在AndroidStudio用户界面的Tools菜单中依次选择Android〉AVDManager。如果大家之前对开发环境的设置工作正确无误,那么Android虚拟设备管理器的界面应该如下图所示。要创建新的AVD,我们需要点击右侧的“New…”、为AVD设定名称并如下图所示对虚拟设备进行配置。最后点击“OK”以创建自己的第一套AVD。要使用我们刚刚创建好的AVD,首先需要在AVD管理器的列表中将其选中,然后点击窗口右侧的“Start…”。如果大家的AVD设置过程正确无误,那么Android模拟器在启动后应该如下图所示。既然Android模拟器已经成功启动并开始运行,现在是时候启动我们的应用程序了。在“Run”菜单中选择“Run‘helloworld’”——没错,在Android模拟器中运行应用程序就是这么简单。3.实时布局(LiveLayout)AndroidStudio中的实时布局功能允许大家在无需将应用程序运行在设备或者模拟器中的前提下,直接预览应用的用户界面。实时布局是一款极为强大的工具,能够帮助开发者节约大量时间。在实时布局的帮助下,查看应用程序用户界面的任务变得轻松而且快捷。要使用实时布局,我们需要双击对应XML布局文件并选择工作区下方的“Text”标签。接下来选择工作区右侧的“Preview”标签来预览当前布局。我们对XML布局作出的任何变更都会直接反映在右侧的预览窗口当中。大家可以查看下面这幅截图来深入理解这项功能。实时布局功能为我们带来了诸多值得称道的显着优势。举例来说,大家可以在Preview面板的第一项菜单中选择选项,从而对当前正在使用的XML布局随意作出调整。譬如说,大家可以分别创建不同的纵向与横向显示视图,AndroidStudio会承担起创建必要文件夹及文件的任务。Preview面板中的第二项菜单允许大家变更显示在Preview面板内的设备大小。第三项菜单的作用则是调整设备在Preview面板中的朝向,这样我们就能更轻松地查看同一套布局方案在不同显示模式(纵向与横向)下的效果与主题。Preview面板中的第四项菜单允许我们轻松访问Activity或者布局所使用的个别片段。Preview面板还允许大家变更在实时布局中使用的语言,从而轻松预览不同语言在布局方案中的显示效果。最右边的菜单的作用则是调整API版本。Preview面板中还包含多项控制机制,例如对布局进行缩放、重新Preview面板或者截取当前屏幕。4.模板AndroidStudio还为开发人员提供多种模板选项,从而大大提升开发速度。这些模板能自动创建Activity以及必要的XML文件。大家还可以利用这些模板创建出较为基础的Android应用程序,并将其运行在实体设备或者模拟器当中。在AndroidStudio当中,我们可以在创建新的Activity时一同创建出对应模板。右键点击窗口左侧项目浏览器中的“packagename”并在菜单中选择“New”,而后从选项列表中点选“Activity”。AndroidStudio随后会为开发者列出模板清单,其中包括BlankActivity、FullscreenActivity以及TabbedActivity。大家还可以从菜单中选择“ImageAsset”,接下来的向导会指引我们一步步完成创建流程。下面让我们一起来看看如何以LoginActivity模板为基础创建一套新的Activity。首先在Acivity模板列表中选择LoginActivity选项以启动创建向导。如大家在上面的截图中所见,我已经将新建的Activity命名为LoginActivity——也就是为activitylogin设定LayoutName——并为该Activity添加了一个名为SignIn的标题。在默认情况下,对话框中的IncludeGoogle+signin项目已经被勾选。由于我们不打算在今天的示例中使用Google+登录功能,因此取消该勾选项。大家可以选择为这套新的Activity设定HierarchicalParent(分层结构)。这样当我们点击设备上的后退按钮时,应用就将通过导航返回至上一界面。我们将这一字段留空。在点击“Finish”之后,AndroidStudio会为我们创建出必要的文件及文件夹。如果一切进展顺利,我们将在项目当中看到新的Activity与Layout。下一布工作是在manifest文件中对新Activity进行设置,这样它就能在应用程序启动时作为主Activity加以使用了。请大家一起来看下面的manifest文件内容,其中LoginActivity类拥有自己的活动节点。为了在应用程序当中启动我们刚刚创建的LoginActivity,首先需要移除原有LoginActivity类的活动节点,然后利用com.tuts.HelloWorld.LoginActivity代替先前的com.tuts.HelloWorld.MainActivity。这样一来,应用程序现在就将使用LoginActivity类作为其主Activity。当我们在模拟器当中创建并运行自己的应用程序时,首先应该会看到如下图所示的显示内容。这意味着我们已经成功利用刚刚创建的LoginActivity类取代了原有的空白Activity类。5.Lint工具对代码进行测试是一回事,但同样重要的是、我们还需要在编写代码的同时引入各种最佳实践。这不仅能够显着改进性能表现,也能增加应用程序的整体稳定性。另外,经过合理结构调整的项目在维护方面也更为轻松。AndroidStudio中提供的AndroidLint是一款静态分析工具,它负责对项目源代码加以分析。它能够检测出应用程序中的潜在漏洞以及其它可能被编译器所忽略的其它代码问题。就以下面这幅截图为例,大家可以看到该布局中的LinearLayout并未得到实际使用。AndroidLint的优势在于,它能帮助我们重视警告或报错信息的出现原因,从而更轻松地修复或者解决这些问题。请大家养成重复使用AndroidStudioLint工具的好习惯,这能帮助我们准确检测到项目当中存在的潜在问题。Lint工具甚至能告诉我们应用程序中是否存在重复的图片或者编译内容。要运行Lint工具,大家首先需要在AndroidStudio的“Analyze”菜单中选择“InspectCode…”。当AndroidStudio完成了对项目的检测之后,它会在窗口底部显示出分析结果。请注意,除了AndroidLint之外,AndroidStudio还提供一系列其它检查功能。只需双击某个已经发现的问题,系统就会帮助大家定位到对应文件中存在问题的位置。6.富布局编辑器AndroidStudio提供一套富布局编辑器,大家可以在其中随意拖拽各类用户界面组件。大家还可以在多屏幕配置中同时查看多种布局的显示效果,这一点我们在前文中已经提到过。这款富布局编辑器在使用方面非常直观简单。我们首先需要一套要处理的布局方案。浏览到项目中res文件夹下的layout文件夹,右键点击layout文件夹,然后在弹出的菜单中选择New>Layoutresourcefile。下面为新布局设定一个名称与root元素,而后点击“OK”。AndroidStudio会自动在窗口右侧的编辑器当中打开该布局。在编辑器的底部,大家会看到两个标签,分别是Design与Text。点击Text标签后编辑器将被激活,这样我们就能对当前选定的布局方案作出变更。点击Design标签则会激活另一套编辑器内容,其中显示出布局的预览效果。要向布局当中添加其它功能性组件,我们只需将其从布局左侧的组件列表中拖出并放入布局内即可。是的,就这么简单。

‘叁’ 如何分析android的OOM,与java静态代码分析工具

1.用MAT分析OOM
很多OOM看似发生在bitmap 分配得时候,但它一般不是rootcause。根本原因都在于本应该自动释放的资源,因为代码的错误,而导致某些对象一直被引用(Reference)。
2.java静态代码分析工具
写代码过程中难免会有疏漏,我们也可以借助工具分析,这里是常用的java静态代码分析工具:
http://www.oschina.net/question/129540_23043
个人觉得Find Bugs 和 PMD就可以了,只是辅助,不必过分依赖,他并不是万能的,不是所有错误都能找出来。

‘肆’ android studio 怎么用findbugs

在Android开发中,会出现一些比较不容易发现的bug,比如对于null的判断,出现遗漏的时候会出现'NullPointException',比如下面的代码:
if (ta != null) {
mPanelHeight = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_umanoPanelHeight, -1);
mShadowHeight = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_umanoShadowHeight, -1);
mParallaxOffset = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_umanoParalaxOffset, -1);

.......
}

ta.recycle();

开头的时候判断ta不为null的情况,但是在调用 ta.recycle() 的时候是在if之外,但调用这个方法的时候,传入的参数ta为null的时候就会出现 NullPointException ,如果能够通过工具找到这种潜在的bug就最好不过了。
FindBugs
FindBugs 是一个Java静态分析工具,用来检查类或者jar文件,用来发现可能的问题。检测完成之后会生成一份详细的报告,借助这份报告可以找到潜在的bug,比如 NullPointException ,特定的资源没有关闭,查询数据库没有调用 Cursor.close() 等,如果才用人工的方式很难才能发现类似的bug,或者这些bug永远不会发现,直到运行时才发现,还有可能是一直没有出现,别人调用的时候没有做检查就调用了.....
Java的静态分析工具当然可以无难度的在Android上面运行,通过这种FindBugs的检查可以让App的运行更加的稳定。
FindBugs官网地址: http://findbugs.sourceforge.net/
Gradle的FindBugs插件
FindBugs在Gradle中是当做一个插件存在的,可以在Android Studio中直接使用:
apply plugin: "findbugs"

task findbugs(type: FindBugs,dependsOn:'assembleDebug') {

ignoreFailures= true
effort= "default"
reportLevel= "high"
println( "$project.buildDir")
classes = files("$project.buildDir/intermediates/classes")
source= fileTree("src/main/java/")
classpath= files()
reports{
xml.enabled=false
html.enabled=true
xml {
destination "$project.buildDir/findbugs.xml"
}
html{
destination "$project.buildDir/findbugs.html"
}
}
}

首先引入 FindBugs 的插件。
定义一个 task 任务,这个任务的类型是 FindBugs ,依赖 assembleDebug 母的是先生成.classe文件。
ignoreFailures :有警告错误的时候也是允许构建。
reportLevel :报告的级别, Low , Medium , High 一般来说我们首先关注的是高级别的报告,再关注低一级别的报告。
classes 和 source 分别是对应的.classe文件夹地址,和源代码文件地址。
repoets 指定报告类型,有两种方式 xml 和 html ,只允许一种输出格式。
在右侧的Gradle的对于的Mole可以在Tasks中找到对应的findBugs任务,点击即可运行。
报告
我们会得到对应的一个类似与这样的报告:
问题发现的例子:
1.NP:`Possible null pointer dereference `,可能出现null的代码。
2.HE:重写对戏那个的equals()方法,但是没有重写它的hashCode方法。或者相反。
3.SE:serializable错误

更多的内容解读可以点击详情,可以看到错误对应的代码行号,和错误详情,以及相关检测错误的解释。
运行时机
什么时候运行是一个问题,一般情况下在原有的项目中加入findBugs之后,会检测出以前的代码存在的一些问题,所以在使用findBugs的时候应该做一次全面的检查,解决到对于的问题。
其他运行的时机,我觉得是,在完成一个版本对应功能的时候要运行检查一次,防止写的代码有潜在的bug,另一个时间点就是在每次修复完Bug之后,在运行一次,防止修复Bug的时候,引入新的Bug。

‘伍’ 如何提高 Android 代码质量

(1)插件安装
在Android Studio中选择Preferences -> Plugins,输入查找findBugs进行插件安装。
(2)插件使用
在build.gradle文件中,按照下面步骤进行设置:
添加plugin apply plugin:’findbugs’
定义任务,指定输出格式
这里要注意因为findBugs是检查class文件,所以在定义task的时候,是dependsOn: “assembleDebug”,确保运行findbugs的task能够成功检测。
通过gradle findbugs方式,在工程目录下运行命令,检测完成后,会在制定的目录下生成报告文档。文档支持xml和html两种格式,本文设置的是html格式,可以直接用浏览器打开。
当然,和lint一样,findBugs也支持手动检测的方式。
在工程里,右键 FindBugs -> (选择检测的范围)。检测完之后,底部工具栏会跳到FindBugs-IEDA下。
3
PMD

PMD是一个很有用的工具,它跟Findbugs类似,但是它不是检测字节码,它是直接检测源代码。它使用静态分析来发现错误。

为什么要将它们同时使用呢?因为它们的检测方法不同,可以取到互补的作用。

检测范围
可能的bug——空的try/catch/finally/switch块。
无用代码(Dead code):无用的本地变量,方法参数和私有方法。
空的if/while语句。
过度复杂的表达式——不必要的if语句,本来可以用while循环但是却用了for循环。
可优化的代码:浪费性能的String/StringBuffer的使用。

(1)插件安装

同样可以通过AS的plugin进行安装,推荐安装QAPlug-PMD。

(2)插件使用

在build.gradle文件中进行如下配置

导入Plugin:apply plugin: ‘pmd’
Task配置

4
CheckStyles

这个工具用来自动检测java源码。启动之后,可以按照制定的规则对java源码进行检查,被将所有的不符合规范的地方生成报告通知给你。

检测范围
注解
javadoc注释
命名规范
文件头
导入包规范
尺寸设置
空格
正则表达式
修饰符
代码块
编码问题
类设计问题
重复、度量以及一些杂项

总而言之,是一些代码规范问题!!

(1)插件安装

通过AS的Plugin进行安装

(2)插件使用

导入Plugin
apply plugin: ‘checkstyle’
设置CheckStyle的版本
checkstyle {
toolVersion ‘6.1.1’
showViolations true
}
配置任务

5
插件的接入与使用

检测范围
lint、PMD、findBugs和CheckStyle检测范围之和。

(1)插件安装

下载整合插件的文件包(文末),和app工程目录同级放置。
在app的build.gradle文件导入整合插件脚本
apply from: ‘../config/quality.gradle’

(2)插件使用

修改quality.gradle 的appDir字段,设置检测的工程目录
// 应用目录名称def appDir = “app-k12”
进入工程根目录,运行gradle check,检测完成后,会在build/reports下生成相应的检测报告文件。当然也可以按照每个插件的使用方式单独使用。

‘陆’ Android Studio怎么用

1.项目设置
在开始畅游Android Studio的世界之前,大家首先需要点击此处下载并进行安装。请注意,各位必须事先安装好JDK 6或者更高版本。如果是在Windows系统环境下,先启动.exe文件、而后按照安装向导的指示一步步完成。如果大家使用的是OS X系统,则首先双击启动磁盘镜像,然后将Android Studio拖拽到自己的应用程序文件夹当中。
在成功完成了以上各项步骤后,那么大家的开发环境应该已经得到了正确设置。接下来,我们可以准备好利用Android Studio创建自己的第一款Android应用程序了。当大家第一次启动Android Studio时,应该会看到该软件的欢迎屏幕,其中还提供一些选项、指导我们以此为起点迈出Android应用开发的第一步。

在今天的教程中,我们将选择“New Project(新项目)”选项。不过如果大家希望把Eclipse等其它环境中的现有项目转化为Android Studio项目,也可以选择“Import Project(导入项目)”。Android Studio能够将Eclipse项目转换为Android Studio项目,并在项目中为用户提供必要的配置文件。
如果大家在选项列表中点击了“Open Project(打开项目)”,则可以开启已经利用Android Studio或者IntelliJ IDEA创建出的项目。而选择“Check out from Version Control(版本控制检查)”的话,大家能够对处于版本控制之下的项目副本进行检查。通过这种方式,我们可以将现有项目作为基础、快速构建起新的针对性版本。
由于我们需要从零开始,因此这里选择“新项目”。这时大家会看到一份选项列表,旨在对我们的新项目作出配置。在今天的教程中,我们将创建一款简单的应用程序,主要目的是为大家演示Android Studio中最为重要的一部分功能特性。相信大家也和我一样,会认为“HelloWorld”这个名称最适合本次开发出的新项目。

正如大家在上面这幅截图中所看到,我把自己的应用程序命名为HelloWorld,并为其设定了模块名称。如果大家对IntelliJ IDEA不太熟悉,可能不知道模块这东西到底是什么。模块实际上就是一个可以进行编译、运行、测试以及调试的独立功能单元。模块当中包含有源代码、编译脚本以及用于特定任务的其它组成部分。
在创建新项目时,大家还可以为该项目设定软件包名称。在默认情况下,Android Studio会将项目包名称的最后一项元素设置为模块名称,但只要愿意、大家可以随意对其作出变更。
其它设定内容还包括项目在设备上的保存位置、最低与推荐SDK、项目编译需要使用的SDK以及项目主题等等。大家也可以要求Android Studio创建一个Activity类、为其自定义一个启动图标,或者设定该项目是否支持GridLayout、Fragments、Navigation Drawer或者Action Bar等。
这里我们不会为自己的应用程序创建自定义图标,因此大家可以取消“Create custom launch icon(创建自定义启动图标)”项目前的勾选框。点击“Next(下一步)”继续进行其它项目设置步骤。
由于我们在之前的步骤中勾选了“Create activity(创建activity)”项目的勾选框,因此这里导航会要求大家对Android Studio将为我们创建的Activity类进行配置。

由于我们将从空白Activity类开始进行配置,因此大家可以点击“Next”执行设置流程的下面几个步骤。这里大家需要对该Activity类、主布局以及片段布局进行命名。大家也可以设置导航类型,在今天的示例项目中我们将其设置为“None”。下面这幅截图显示的是我们的设置方案看起来是什么样子。

在点击“Finish”之后,大家会看到如下图所示的Android Studio用户界面。其中窗口左侧为项目资源管理器,右侧则为工作区。在Android Studio中对项目进行设置之后,现在我们可以逐一查看Android Studio当中的各项关键功能。

2. Android虚拟设备
所谓Android虚拟设备——或者简称AVD——是一套模拟器配置方案,它允许大家设定出与实际情况相符的Android设备型号。这就让开发者在多种多样的设备平台上运行并测试应用程序变得更为轻松。在Android虚拟设备功能的支持下,大家可以为Android模拟器指定需要模拟的硬件与软件组合。
创建Android虚拟设备的首选方式是通过AVD Manager。大家可以在Android Studio用户界面的Tools菜单中依次选择Android〉AVD Manager。

如果大家之前对开发环境的设置工作正确无误,那么Android虚拟设备管理器的界面应该如下图所示。

要创建新的AVD,我们需要点击右侧的“New…”、为AVD设定名称并如下图所示对虚拟设备进行配置。最后点击“OK”以创建自己的第一套AVD。

要使用我们刚刚创建好的AVD,首先需要在AVD管理器的列表中将其选中,然后点击窗口右侧的“Start…”。如果大家的AVD设置过程正确无误,那么Android模拟器在启动后应该如下图所示。

既然Android模拟器已经成功启动并开始运行,现在是时候启动我们的应用程序了。在“Run”菜单中选择“Run ‘helloworld’”——没错,在Android模拟器中运行应用程序就是这么简单。

3.实时布局(Live Layout)
Android Studio中的实时布局功能允许大家在无需将应用程序运行在设备或者模拟器中的前提下,直接预览应用的用户界面。实时布局是一款极为强大的工具,能够帮助开发者节约大量时间。在实时布局的帮助下,查看应用程序用户界面的任务变得轻松而且快捷。
要使用实时布局,我们需要双击对应XML布局文件并选择工作区下方的“Text”标签。接下来选择工作区右侧的“Preview”标签来预览当前布局。我们对XML布局作出的任何变更都会直接反映在右侧的预览窗口当中。大家可以查看下面这幅截图来深入理解这项功能。

实时布局功能为我们带来了诸多值得称道的显着优势。举例来说,大家可以在Preview面板的第一项菜单中选择选项,从而对当前正在使用的XML布局随意作出调整。譬如说,大家可以分别创建不同的纵向与横向显示视图,Android Studio会承担起创建必要文件夹及文件的任务。
Preview面板中的第二项菜单允许大家变更显示在Preview面板内的设备大小。第三项菜单的作用则是调整设备在Preview面板中的朝向,这样我们就能更轻松地查看同一套布局方案在不同显示模式(纵向与横向)下的效果与主题。
Preview面板中的第四项菜单允许我们轻松访问Activity或者布局所使用的个别片段。Preview面板还允许大家变更在实时布局中使用的语言,从而轻松预览不同语言在布局方案中的显示效果。最右边的菜单的作用则是调整API版本。
Preview面板中还包含多项控制机制,例如对布局进行缩放、重新Preview面板或者截取当前屏幕。
4.模板
Android Studio还为开发人员提供多种模板选项,从而大大提升开发速度。这些模板能自动创建Activity以及必要的XML文件。大家还可以利用这些模板创建出较为基础的Android应用程序,并将其运行在实体设备或者模拟器当中。
在Android Studio当中,我们可以在创建新的Activity时一同创建出对应模板。右键点击窗口左侧项目浏览器中的“package name”并在菜单中选择“New”,而后从选项列表中点选“Activity”。Android Studio随后会为开发者列出模板清单,其中包括Blank Activity、Fullscreen Activity以及Tabbed Activity。

大家还可以从菜单中选择“Image Asset”,接下来的向导会指引我们一步步完成创建流程。下面让我们一起来看看如何以Login Activity模板为基础创建一套新的Activity。首先在Acivity模板列表中选择Login Activity选项以启动创建向导。

如大家在上面的截图中所见,我已经将新建的Activity命名为LoginActivity——也就是为activity login设定Layout Name——并为该Activity添加了一个名为Sign In的标题。在默认情况下,对话框中的Include Google+ sign in项目已经被勾选。由于我们不打算在今天的示例中使用Google+登录功能,因此取消该勾选项。
大家可以选择为这套新的Activity设定Hierarchical Parent(分层结构)。这样当我们点击设备上的后退按钮时,应用就将通过导航返回至上一界面。我们将这一字段留空。在点击“Finish”之后,Android Studio会为我们创建出必要的文件及文件夹。如果一切进展顺利,我们将在项目当中看到新的Activity与Layout。
下一布工作是在manifest文件中对新Activity进行设置,这样它就能在应用程序启动时作为主Activity加以使用了。请大家一起来看下面的manifest文件内容,其中LoginActivity类拥有自己的活动节点。
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.tuts.HelloWorld.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.tuts.HelloWorld.LoginActivity"
android:label="@string/title_activity_login"
android:windowSoftInputMode="adjustResize|stateVisible" >
</activity>
</application>

为了在应用程序当中启动我们刚刚创建的LoginActivity,首先需要移除原有LoginActivity类的活动节点,然后利用com.tuts.HelloWorld.LoginActivity代替先前的com.tuts.HelloWorld.MainActivity。这样一来,应用程序现在就将使用LoginActivity类作为其主Activity。
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="za.co.helloworld.LoginActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

当我们在模拟器当中创建并运行自己的应用程序时,首先应该会看到如下图所示的显示内容。这意味着我们已经成功利用刚刚创建的LoginActivity类取代了原有的空白Activity类。

5.Lint工具
对代码进行测试是一回事,但同样重要的是、我们还需要在编写代码的同时引入各种最佳实践。这不仅能够显着改进性能表现,也能增加应用程序的整体稳定性。另外,经过合理结构调整的项目在维护方面也更为轻松。
Android Studio中提供的Android Lint是一款静态分析工具,它负责对项目源代码加以分析。它能够检测出应用程序中的潜在漏洞以及其它可能被编译器所忽略的其它代码问题。
就以下面这幅截图为例,大家可以看到该布局中的LinearLayout并未得到实际使用。Android Lint的优势在于,它能帮助我们重视警告或报错信息的出现原因,从而更轻松地修复或者解决这些问题。

请大家养成重复使用Android Studio Lint工具的好习惯,这能帮助我们准确检测到项目当中存在的潜在问题。Lint工具甚至能告诉我们应用程序中是否存在重复的图片或者编译内容。
要运行Lint工具,大家首先需要在Android Studio的“Analyze”菜单中选择“Inspect Code…”。当Android Studio完成了对项目的检测之后,它会在窗口底部显示出分析结果。请注意,除了Android Lint之外,Android Studio还提供一系列其它检查功能。只需双击某个已经发现的问题,系统就会帮助大家定位到对应文件中存在问题的位置。

6.富布局编辑器
Android Studio提供一套富布局编辑器,大家可以在其中随意拖拽各类用户界面组件。大家还可以在多屏幕配置中同时查看多种布局的显示效果,这一点我们在前文中已经提到过。
这款富布局编辑器在使用方面非常直观简单。我们首先需要一套要处理的布局方案。浏览到项目中res文件夹下的layout文件夹,右键点击layout文件夹,然后在弹出的菜单中选择New>Layout resource file。
下面为新布局设定一个名称与root元素,而后点击“OK”。Android Studio会自动在窗口右侧的编辑器当中打开该布局。

在编辑器的底部,大家会看到两个标签,分别是Design与Text。点击Text标签后编辑器将被激活,这样我们就能对当前选定的布局方案作出变更。
点击Design标签则会激活另一套编辑器内容,其中显示出布局的预览效果。要向布局当中添加其它功能性组件,我们只需将其从布局左侧的组件列表中拖出并放入布局内即可。是的,就这么简单。

‘柒’ Android单元测试都是测一些什么

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
在一种传统的结构化编程语言中,比如C,要进行测试的单元一般是函数或子过程。在像C++这样的面向对象的语言中, 要进行测试[1] 的基本单元是类。对Ada语言来说,开发人员可以选择是在独立的过程和函数,还是在Ada包的级别上进行单元测试。单元测试的原则同样被扩展到第四代语言(4GL)的开发中,在这里基本单元被典型地划分为一个菜单或显示界面。
经常与单元测试联系起来的另外一些开发活动包括代码走读(Code review),静态分析(Static analysis)和动态分析(Dynamic analysis)。静态分析就是对软件的源代码进行研读,查找错误或收集一些度量数据,并不需要对代码进行编译和执行。动态分析就是通过观察软件运行时的动作,来提供执行跟踪,时间分析,以及测试覆盖度方面的信息。

‘捌’ 分析程序软件您觉得通过哪些方式有几种办法可以实现

方法通过静态分析方式和动态分析方式相结合,实现应用程序行为分析检测。静态分析通过Android的静态反汇编和反编译获取应用程序的源代码和资源配置文件,然后通过检测源代码中是否包含敏感行为特征,实现静态行为分析检测。动态分析结合沙箱系统,实现程序的动态运行并输出行为日志,然后对输出的行为日志分析,实现对应用程序动态行为分析检测。静态分析由于某些程序精心构造,无法对一些未将特征编码在代码文件中行为进行分析,在检测时无法获取潜在的应用程序行为;动态分析由于自动运行行为的随机性,不能完全触发应用程序操作。两种方式都存在这不足,所以本课题在实现分析系统时采取了动静态分析相结合方式,以更全面的实现Android应用程序的行为分析检测,为安全分析提供依据。

‘玖’ 如何分析android的oom,与java静态代码分析工具

在Android平台上面,应用程序OOM异常永远都是值得关注的问题。通常这一块也是程序这中的重点之一。这下我就如何解决OOM作一点简单的介绍。
首先,OOM就是内存溢出,即Out Of Memory。也就是说内存占有量超过了VM所分配的最大。
怎么解决OOM,通常OOM都发生在需要用到大量内存的情况下(创建或解析Bitmap,分配特大的数组等),在这样的一种情况下,就可能出现OOM,据我现在了解到,多数OOM都是因为Bitmap太大。所以,这里我就专门针对如何解决Bitmap的OOM。其实最核发的就是只加载可见范围内的Bitmap,试想这样一种情况,在GridView或ListView中,数据量有5000,每一屏只显示20个元素,那么不可见的,我们是不需要保存Bitmap在内在中的。所以我们就是只把那么可见的Bitmap保留在内存中,那些不可见的,就释放掉。当元素滑出来时,再去加载Bitmap。
这里我有两种方式,都可以避免OOM。
一,主动释放Bitmap的内存
这种方式我简单说一下,不太推荐,这也是我最开始使用的一种方法,但最后证明它不是最好的。(不推荐)
它的本质思路是:
1、只加载可见区域的Bitmap
2、滑动时不加载
3、停止滑动(Idle)后,开始重新加载可见区域的图片
4、释放滑出可见区域的Bitmap的内在。
它比较复杂:
1、我们需要监听GridView/ListView的滑动事件,这个很简单做到,AbsListView#setOnScrollListener(OnScrollListener l)
2、主动调用Bitmap#recycle()方法,它会导致一个问题,必须判断这个Bitmap是否被一个View(ImageView等)所引用,如果被引用,我们不能简单地调用recycle()方法,这样会导致异常,说是View使用了一个已经被回收的Bitmap。
3,我们必须设计自己的线程来控制开始/暂停等,因为GridView/ListView的滑动状态可能不断地变化,也就是说滑动->停止->滑动,这种状态可能不断变化,这样就会导致我们的线程中的run()方法里面的逻辑比较复杂,一旦复杂,问题就可能就得更多。
基于以上几点,这种方式不是最好的,所以不推荐。
二,设计Cache
这种方式,我觉得是比较好的一种,它首先利用了cache,我认为cache是一个很重要的东西,把Bitmap的内存单独放在一个地方来管理,这个地方就是cache,它的容量是一定的,我们可能会不断的向这个cache中添加元素,也可能不断的移除元素。
为了更好的说明这种方式,先要介绍一下LruCache。
LruCache
1、这其实就是一个LinkedHashMap,任意时刻,当一个值被访问时,它就会被移动到队列的开始位置,所以这也是为什么要用LinkedHashMap的原因,因为要频繁的做移动操作,为了提高性能,所以要用LinkedHashMap。当cache满了时,此时再向cache里面添加一个值,那么,在队列最后的值就会从队列里面移除,这个值就有可能被GC回收掉。

‘拾’ 静态分析是指

经济领域概念
静态分析是一种分析经济现象的均衡状态以及有关的经济变量达到均衡状态所需要条件的分析方法。[1]而不考虑经济现象达到均衡状态的过程,它完全抽象掉了时间因素和具体的变化过程,是一种静止地、孤立地考察某种经济事物的方法。
网络


静态分析
经济领域概念
静态分析是一种分析经济现象的均衡状态以及有关的经济变量达到均衡状态所需要条件的分析方法。[1]而不考虑经济现象达到均衡状态的过程,它完全抽象掉了时间因素和具体的变化过程,是一种静止地、孤立地考察某种经济事物的方法。

中文名
静态分析
外文名
static analysis
指标
总量指标、相对指标、平均指标、标志变异指标等
应用
静态计算机科学、经济学、工程、力学、机械
释义
根据既定的外生变量值求得内生变量的分析方法
内涵
静态分析法是根据既定的外生变量值求得内生变量的分析方法,是对已发生的经济活动成果,进行综合性的对比分析的一种分析方法。

如研究均衡价格时,舍掉时间、地点等因素,并假定影响均衡价格的其他因素,如消费者偏好、收入及相关商品的价格等静止不变,单纯分析该商品的供求达于均衡状态的产量和价格的决定。简单地说就是抽象了时间因素和具体变动的过程,静止地孤立地考察某些经济现象。它一般用于分析经济现象的均衡状态以及有关经济变量达到均衡状态所需要的条件。

常用的静态分析法有:相对数分析法、平均数分析法、比较分析法、结构分析法、因素替换分析法、综合计算分析法、价值系数分析法等。

指标

热点内容
文件夹侧边条 发布:2025-03-10 12:50:22 浏览:383
液化天然气存储 发布:2025-03-10 12:47:28 浏览:717
压缩机介质端 发布:2025-03-10 12:46:00 浏览:19
linux的测试 发布:2025-03-10 12:45:10 浏览:277
黑客说编程 发布:2025-03-10 12:23:57 浏览:841
服务器无法登录什么时候才能登录 发布:2025-03-10 12:17:20 浏览:888
微云密码是什么 发布:2025-03-10 12:13:26 浏览:86
android上拉下拉 发布:2025-03-10 12:07:05 浏览:915
缓存大好 发布:2025-03-10 11:55:42 浏览:838
搭建java 发布:2025-03-10 11:47:00 浏览:524