首页 文章 精选 留言 我的

精选列表

搜索[类型注释],共10000篇文章
优秀的个人博客,低调大师

Android开发笔记——常见BUG类型之内存泄露与线程安全

一、内存泄露 1、很抱歉,”XXX”已停止运行。OOM? 怎样才能让app报OOM呢?最简单的办法如下: Bitmapbt1=BitmapFactory.decodeResource(this.getResources(),R.drawable.image); Bitmapbt2=BitmapFactory.decodeResource(this.getResources(),R.drawable.image); Bitmapbtn=... 2、查看内存占用 命令行:adb shell dumpsys meminfopackageName 通过Android Studio的Memory Monitor查看内存中Dalvik Heap的实时变化 3、发生内存泄露的条件 首先,每个app有最大内存限制。 ActivityManageractivityManager=(ActivityManager)context.getSystemServiceContext.ACTIVITY_SERVICE); activityManager.getMemoryClass(); getMemoryClass()取到的是最大内存资源。Android中的堆内存分为NativeHeap和DalvikHeap。C/C++申请的内存空间在NativeHeap中,Java申请的内存空间则在DalvikHeap中。对于head堆的大小限制,可以查看/system/build.prop文件: dalvik.vm.heapstartsize=8m dalvik.vm.heapgrowthlimit=96m dalvik.vm.heapsize=256m 注意: heapsize参数表示单个进程heap可用的最大内存,但如果存在以下参数”dalvik.vm.headgrowthlimit =96m”表示单个进程heap内存被限定在96m,即程序运行过程实际只能使用96m内存。 如果申请的内存资源超过上述限制,系统就会抛出OOM错误。 4、常见避免OOM的措施 以下主要从四个方面总结常见的措施:1)减小对象的内存占用;2)内存对象的重复利用;3)避免对象的内存泄露;4)内存使用策略优化。 4.1 减小对象的内存占用 使用ArrayMap/SparseArray而不是HashMap等传统数据结构。 参考链接:Android内存优化(使用SparseArray和ArrayMap代替HashMap) 在Android中避免使用枚举。 减小Bitmap对象的内存占用。inSampleSize和decode format。 4.2 内存对象的重复利用 ListView/GridView等出现大量重复子组件的视图里面对ConvertView的复用 使用LRU机制缓存Bitmap 避免在onDraw方法里面执行对象的创建 使用StringBuilder来替代频繁的”+” 4.3 避免对象的内存泄露 4.1和4.2都是比较常规的措施,4.3需要重点关注。 1)Activity泄露 导致Activity泄露的原因较多,下面列举一些比较常见的。从原理上主要分为两类:i)静态对象;ii)this$0。 Activity被static变量引用。这段代码来自于我们的Crash上传 privatestaticMap<ComponentName,ExceptionHandler>configMap= newHashMap<ComponentName,ExceptionHandler>();publicstaticvoidsetActivity(finalActivityactivity,booleansend2Server){ Log.d(TAG,"bindexceptionhandler:"+activity.getComponentName().getClassName());//上下文初始化SDKContext.init(activity.getApplication()); init(activity.getApplication()); ExceptionHandlerexceptionHandler=newExceptionHandler( activity,send2Server,Thread.getDefaultUncaughtExceptionHandler()); configMap.put(activity.getComponentName(),exceptionHandler); Thread.setDefaultUncaughtExceptionHandler(exceptionHandler); } 下面是通过MAT分析一个Activity泄露的截图: 内部类引用导致Activity的泄漏 最典型的场景是Handler导致的Activity泄漏,如果Handler中有延迟的任务或者是等待执行的任务队列过长,都有可能因为Handler继续执行而导致Activity发生泄漏。此时的引用关系链是Looper -> MessageQueue -> Message -> Handler -> Activity。为了解决这个问题,可以在UI退出之前,执行remove Handler消息队列中的消息与runnable对象。或者是使用Static + WeakReference的方式来达到断开Handler与Activity之间存在引用关系的目的。 可参考链接:线程通信 2)考虑使用Application Context而不是Activity Context 对于大部分非必须使用Activity Context的情况(Dialog的Context就必须是Activity Context),我们都可以考虑使用Application Context而不是Activity的Context,这样可以避免不经意的Activity泄露。 3)注意临时Bitmap对象的及时回收 虽然在大多数情况下,我们会对Bitmap增加缓存机制,但是在某些时候,部分Bitmap是需要及时回收的。例如临时创建的某个相对比较大的bitmap对象,在经过变换得到新的bitmap对象之后,应该尽快回收原始的bitmap,这样能够更快释放原始bitmap所占用的空间。 4)内存占用监控 通过Runtime获取maxMemory,而maxMemory-totalMemory即为剩余可使用的dalvik内存。定期检查这个值,达到80%就去释放各种cache资源(bitmap的cache)。 /** *Returnsthemaximumnumberofbytestheheapcanexpandto.See{@link#totalMemory}forthe *currentnumberofbytestakenbytheheap,and{@link#freeMemory}forthecurrentnumberof *thosebytesactuallyusedbyliveobjects.*/intmaxMemory=Runtime.getRuntime().maxMemory());//应用程序最大可用内存/** *Returnsthenumberofbytestakenbytheheapatitscurrentsize.Theheapmayexpandor *contractovertime,asthenumberofliveobjectsincreasesordecreases.See *{@link#maxMemory}forthemaximumheapsize,and{@link#freeMemory}foranideaofhowmuch *theheapcouldcurrentlycontract.*/longtotalMemory=Runtime.getRuntime().totalMemory());//应用程序已获得内存/** *Returnsthenumberofbytescurrentlyavailableontheheapwithoutexpandingtheheap.See *{@link#totalMemory}fortheheap'scurrentsize.Whenthesebytesareexhausted,theheap *mayexpand.See{@link#maxMemory}forthatlimit.*/longfreeMemory=Runtime.getRuntime().freeMemory());//应用程序已获得内存中未使用内存 5)注意Cursor对象是否及时关闭 在程序中我们经常会进行查询数据库的操作,但时常会存在不小心使用Cursor之后没有及时关闭的情况。这些Cursor的泄露,反复多次出现的话会对内存管理产生很大的负面影响,我们需要谨记对Cursor对象的及时关闭。 4.4 内存使用策略优化 谨慎使用large heap 综合考虑设备内存阈值与其他因素设计合适的缓存大小 onLowMemory()/onTrimMemory(int) 资源文件需要选择合适的文件夹进行存放 Try catch某些大内存分配的操作 谨慎使用static对象 优化布局层次,减少内存消耗 谨慎使用多进程 谨慎使用依赖注入框架 使用ProGuard来剔除不需要的代码 谨慎使用第三方libraries 考虑不同的实现方式来优化内存占用 二、线程安全 1、下面的方法是线程安全的吗? 怎样使上述方法线程安全? 2、Java中的线程安全 怎样保持在多线程环境下的数据一致性,Java提供了多种方法实现: synchronized java.util.concurrent.atomic java.util.concurrent.locks thread safe collection(ConcurrentHashMap) volatile 2.1 synchronized JVM保证被synchronized关键字修饰的代码段在同一时间只能被一个线程访问,内部通过对对象或类加锁来实现的。当方法被synchronized修饰时,锁加在对象上;当方法同时为static时,锁加在类上。从性能的角度来讲,一般不建议直接将锁加在类上,这样会使得类的所有对象的该方法均为synchronized的。 从之前扫描的问题来看,在编写synchronized程序时主要有两点需要注意: synchronized需要创建基于对象或者类的锁,所以不能在构造器或者变量上加锁。 synchronized造成死锁。 1) 锁加在哪里? List<ResultPoint>currentPossible=possibleResultPoints; List<ResultPoint>currentLast=lastPossibleResultPoints;intframeLeft=frame.left;intframeTop=frame.top;if(currentPossible.isEmpty()){ lastPossibleResultPoints=null; }else{ possibleResultPoints=newArrayList<>(5); lastPossibleResultPoints=currentPossible; paint.setAlpha(CURRENT_POINT_OPACITY); paint.setColor(resultPointColor);synchronized(currentPossible){for(ResultPointpoint:currentPossible){ canvas.drawCircle(frameLeft+(int)(point.getX()*scaleX),frameTop+(int)(point.getY()*scaleY),POINT_SIZE, paint); } } } 上述方法中,possibleResultPoints的创建没有采用同步措施,需要使用Collections.synchronizedXxx。 List<MyType>list=Collections.synchronizedList(newArrayList(<MyType>)); ...synchronized(list){for(MyTypem:list){ foo(m); m.doSomething(); } } 一般比较推荐创建一个虚拟的对象专门用于获取锁。 //dummyobjectvariableforsynchronizationprivateObjectmutex=newObject(); ...//usingsynchronizedblocktoread,incrementandupdatecountvaluesynchronouslysynchronized(mutex){ count++; } PS:直接在方法上加synchronized可能DoS攻击喔,举个栗子: publicclassMyObject{//Locksontheobject'smonitor publicsynchronizedvoiddoSomething(){ //...} }//黑客的代码MyObjectmyObject=newMyObject();synchronized(myObject){while(true){//IndefinitelydelaymyObjectThread.sleep(Integer.MAX_VALUE); } } 黑客的代码获取了MyObject对象的锁,导致doSomething死锁,从而引发Denial of Service。 publicclassMyObject{//locksontheclassobject'smonitor publicstaticsynchronizedvoiddoSomething(){ //...} }//黑客的代码synchronized(MyObject.class){while(true){ Thread.sleep(Integer.MAX_VALUE);//IndefinitelydelayMyObject} } 2) 死锁。 publicclassThreadDeadlock{publicstaticvoidmain(String[]args)throwsInterruptedException{ Objectobj1=newObject(); Objectobj2=newObject(); Objectobj3=newObject(); Threadt1=newThread(newSyncThread(obj1,obj2),"t1"); Threadt2=newThread(newSyncThread(obj2,obj3),"t2"); Threadt3=newThread(newSyncThread(obj3,obj1),"t3"); t1.start(); Thread.sleep(5000); t2.start(); Thread.sleep(5000); t3.start(); } }classSyncThreadimplementsRunnable{privateObjectobj1;privateObjectobj2;publicSyncThread(Objecto1,Objecto2){this.obj1=o1;this.obj2=o2; } @Overridepublicvoidrun(){ Stringname=Thread.currentThread().getName(); System.out.println(name+"acquiringlockon"+obj1);synchronized(obj1){ System.out.println(name+"acquiredlockon"+obj1); work(); System.out.println(name+"acquiringlockon"+obj2);synchronized(obj2){ System.out.println(name+"acquiredlockon"+obj2); work(); } System.out.println(name+"releasedlockon"+obj2); } System.out.println(name+"releasedlockon"+obj1); System.out.println(name+"finishedexecution."); }privatevoidwork(){try{ Thread.sleep(30000); }catch(InterruptedExceptione){ e.printStackTrace(); } } } 本文转自xsster51CTO博客,原文链接:http://blog.51cto.com/12945177/1929765 ,如需转载请自行联系原作者

优秀的个人博客,低调大师

Firefox OS试水物联网应用:包括Samantha类型的虚拟助手

去年12月的时候,Mozilla宣布Firefox OS折戟移动市场,并转而将之用于全新的领域。除了松下的新款智能电视,它还将在物联网(IoT)领域施展一番。Mozilla已经推出了一份IoT清单,首当其冲的是一个“私人助理”。其主打智能家居类应用,为IoT设备提供了诸多的传感器和语音接口。Mozilla现正寻找社区成员来帮助开发和测试。 Project Link被描述为“懂你喜好的私人助理”,比如你希望如何与家中的设备互动,并给你带来自动化的连接体验。该项目最初叫做FoxLink,理念是打造出无需人们手动干预的连接设备(尽管它本身还是受人控制的)。 Mozilla对于智能的愿景,不禁让我们联想到了电影《她》(Her)中的私人助理“萨曼莎”(Samantha),不过Mozilla表示该项目仍处于非常早期的阶段。 Project Sensor Web则是打造一个充满了传感器的网络,为人们的访问而汇集各方面的数据。当然这不能和蓝色巨人IBM的“沃森”(Watson)相比,不过用来可视化呈现PM2.5数据之类的数据,还是不在话下的。 Project Smart Home则是Mozilla对于苹果HomeKit、以及树莓派DIY解决方案的一个“中层”回答。作为一个平台,它能够为两网家庭设备制造商提供软硬件方面的运行建议。 最后要介绍的是Vaani项目,如果Link是Samantha的对应版本,那么Vaani就是它的声音部分。开发者可以将这个语音接口添加到自己的应用或硬件产品中,从而让用户的交互更加自然。 本文转自d1net(转载)

优秀的个人博客,低调大师

【Spark Summit East 2017】Spark,类型函数式编程的引诱者

更多精彩内容参见云栖社区大数据频道https://yq.aliyun.com/big-data;此外,通过Maxcompute及其配套产品,低廉的大数据分析仅需几步,详情访问https://www.aliyun.com/product/odps。 本讲义出自Jeff Smith与Rohan Aletty在Spark Summit East 2017上的演讲,主要介绍了如何使用Spark作为学习工具,在函数式编程等领域构建技能栈,介绍了从基础工作Scala和函数式编程的概念到完全实现机器学习管道,并讲解了Spark以及MLlib。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册