Android性能优化第(七)篇---StrickMode严苛模式检测耗时与内存问题

本文主要是介绍Android性能优化第(七)篇---StrickMode严苛模式检测耗时与内存问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

StrictMode意思为严格模式,是用来检测程序中违例情况的开发者工具。使用一般是场景是检测主线程中本地磁盘和网络读写等耗时的操作。注意这个StrictMode是在Anroid2.3以后引入的。严格模式主要检测两大问题,一个是线程策略,即TreadPolicy,另一个是VM策略,即VmPolicy。

线程策略(ThreadPolicy)检测的内容有

  • 1、自定义的耗时调用 使用detectCustomSlowCalls()开启
  • 2、磁盘读取操作 使用detectDiskReads()开启
  • 3、磁盘写入操作 使用detectDiskWrites()开启
  • 4、网络操作 使用detectNetwork()开启

虚拟机策略(VmPolicy)检测的内容有

  • 1、Activity泄露 使用detectActivityLeaks()开启
  • 2、未关闭的Closable对象泄露 使用detectLeakedClosableObjects()开启
  • 3、泄露的Sqlite对象 使用detectLeakedSqlLiteObjects()开启
  • 4、检测实例数量 使用setClassInstanceLimit()开启

可以看到线程策略主要与异步处理相关,虚拟机策略主要与内存管理相关。setThreadPolicy()将对当前线程应用该策略。如果不指定检测函数,也可以用detectAll()来替代。penaltyLog()表示将警告输出到LogCat,你也可以使用其他或增加新的惩罚(penalty)函数,例如使用penaltyDeath()的话,一旦StrictMode消息被写到LogCat后应用就会崩溃。另外虚拟机策略(VmPolicy)不能通过一个对话框提供警告。

在线程策略(ThreadPolicy)检测的时候,有几个penalty系列方法。

  • 1、penaltyDeath(),当触发违规条件时,直接Crash掉当前应用程序。
  • 2、penaltyDeathOnNetwork(),当触发网络违规时,Crash掉当前应用程序。
  • 3、penaltyDialog(),触发违规时,显示对违规信息对话框。
  • 4、penaltyFlashScreen(),会造成屏幕闪烁,不过一般的设备可能没有这个功能。

如何使用严格模式

严格模式的开启可以放在Application或者Activity以及其他组件的onCreate方法。为了更好地分析应用中的问题,建议放在Application的onCreate方法中。设置一次就够了。

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll()//开启所有的detectXX系列方法.penaltyDialog()//弹出违规提示框.penaltyLog()//在Logcat中打印违规日志.build());requestDataFromNet();}/*** 请求数据*/private void requestDataFromNet() {URL url;try {url = new URL("http://www.baidu.com");HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.connect();BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));String lines ;StringBuilder sb = new StringBuilder();while ((lines = reader.readLine()) != null) {sb.append(lines);}Log.d("response",sb.toString());} catch (Exception e) {e.printStackTrace();}}
}

比如上面代码运行之后,就会有下面的弹窗出来警告。 

看一下logcat的日志,是在主线程中做了访问网络的操作。

12-19 17:28:54.226 2729-2729/? D/StrictMode: StrictMode policy violation; ~duration=44 ms: android.os.StrictMode$StrictModeNetworkViolation: policy=63 violation=4at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1123)at java.net.InetAddress.lookupHostByName(InetAddress.java:385)at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)at java.net.InetAddress.getAllByName(InetAddress.java:214)at libcore.net.http.HttpConnection.<init>(HttpConnection.java:70)at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316)at libcore.net.http.HttpEngine.connect(HttpEngine.java:311)at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)at zhangwan.wj.com.myshare.MainActivity.requestDataFromNet(MainActivity.java:35)at zhangwan.wj.com.myshare.MainActivity.onCreate(MainActivity.java:27)at android.app.Activity.performCreate(Activity.java:5104)at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1092)at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2254)at android.app.ActivityThread.access$600(ActivityThread.java:141)at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)at android.os.Handler.dispatchMessage(Handler.java:99)at android.os.Looper.loop(Looper.java:137)at android.app.ActivityThread.main(ActivityThread.java:5069)at java.lang.reflect.Method.invokeNative(Native Method)at java.lang.reflect.Method.invoke(Method.java:511)at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)at dalvik.system.NativeStart.main(Native Method)

上面分析了是异步处理相关的例子,现在分析一个内存管相关的例子,比如检测内存泄露检测,用StrickMode怎么搞?

 public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectActivityLeaks()//检测Activity泄露.penaltyLog()//在Logcat中打印违规日志.build());UserManger instance = UserManger.getInstance(this);}}

比如上面的代码UserManger持有了Activity的引用,当反复进入Activity的时候,Activity不能被回收,导致了内存泄露,此时看Logcat。

12-20 09:57:07.626 4787-4787/? E/StrictMode: class zhangwan.wj.com.myshare.MainActivity; instances=3; limit=1android.os.StrictMode$InstanceCountViolation: class zhangwan.wj.com.myshare.MainActivity; instances=3; limit=1at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)

明确告诉我们instances=3,说明泄露了3个MainActivity对象

严格模式除了可以检测Activity的内存泄露之外,还能自定义检测类的对象泄露。这个从从API 11 开始。

public
StrictMode.VmPolicy.Builder setClassInstanceLimit (Class klass, int instanceLimit)

比如,检测UserManger有没有泄露,可以这么写。

StrictMode.setVmPolicy(new VmPolicy.Builder().setClassInstanceLimit(UserManger.class, 1).penaltyLog().build());

在比如detectLeakedClosableObjects() 和 detectLeakedSqlLiteObjects(),资源没有正确关闭时回触发,detectLeakedRegistrationObjects() 用来检查 BroadcastReceiver 或者 ServiceConnection 注册类对象是否被正确释放等。

StrictMode有个更直接的办法,在部分手机上,可以在开发者选项中开启严格模式,开启之后,如果主线程中有执行时间长的操作,屏幕则会闪烁。OKStrictMode比较简单,到此结束!

这篇关于Android性能优化第(七)篇---StrickMode严苛模式检测耗时与内存问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/755140

相关文章

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

解决RocketMQ的幂等性问题

《解决RocketMQ的幂等性问题》重复消费因调用链路长、消息发送超时或消费者故障导致,通过生产者消息查询、Redis缓存及消费者唯一主键可以确保幂等性,避免重复处理,本文主要介绍了解决RocketM... 目录造成重复消费的原因解决方法生产者端消费者端代码实现造成重复消费的原因当系统的调用链路比较长的时

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

SpringBoot监控API请求耗时的6中解决解决方案

《SpringBoot监控API请求耗时的6中解决解决方案》本文介绍SpringBoot中记录API请求耗时的6种方案,包括手动埋点、AOP切面、拦截器、Filter、事件监听、Micrometer+... 目录1. 简介2.实战案例2.1 手动记录2.2 自定义AOP记录2.3 拦截器技术2.4 使用Fi

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

kkFileView启动报错:报错2003端口占用的问题及解决

《kkFileView启动报错:报错2003端口占用的问题及解决》kkFileView启动报错因office组件2003端口未关闭,解决:查杀占用端口的进程,终止Java进程,使用shutdown.s... 目录原因解决总结kkFileViewjavascript启动报错启动office组件失败,请检查of

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

java内存泄漏排查过程及解决

《java内存泄漏排查过程及解决》公司某服务内存持续增长,疑似内存泄漏,未触发OOM,排查方法包括检查JVM配置、分析GC执行状态、导出堆内存快照并用IDEAProfiler工具定位大对象及代码... 目录内存泄漏内存问题排查1.查看JVM内存配置2.分析gc是否正常执行3.导出 dump 各种工具分析4.