Android Development notes-memory leaks and thread safety for common bug types

Source: Internet
Author: User
Tags message queue try catch

This article is based on a summary of the most recent internal sharing, no time for detailed collation, forgive me.

This share mainly on the memory leaks and thread safety of the two issues are described, internal code scan found the bug roughly divided into four categories: 1) null pointer; 2) memory, resource disclosure, 4) thread safety. The first to second problem is poorly coded, and the third to fourth requires more in-depth analysis.

    1. Memory leaks
    2. Thread Safety
One, memory leaks 1, I am sorry, "XXX" has stopped running. OOM?

How can I get the app to report Oom? The simplest approach is as follows:

Bitmap bt1 = Bitmapfactory.decoderesource (this = Bitmapfactory.decoderesource ( This = ...
2. View memory consumption
    • Command line: adb shell dumpsys meminfo PackageName

    • View real-time changes to the Dalvik heap in memory with Android Studio Memories Monitor

3. Condition of memory leak

First, each app has a maximum memory limit.

Activitymanager Activitymanager = (Activitymanager) Context.getSystemServiceContext.ACTIVITY_SERVICE); Activitymanager.getmemoryclass ();
Getmemoryclass () takes the maximum memory resource. Heap memory in Android is divided into native heap and Dalvik heap. The memory space requested by C + + is in the native heap, and the memory space requested by Java is in the Dalvik heap. For the size limit of the head heap, you can view the/system/build.prop file:
dalvik.vm.heapstartsize=8mdalvik.vm.heapgrowthlimit=96mdalvik.vm.heapsize=256m

The HeapSize parameter represents the maximum amount of memory available for a single process heap, but if the following parameter "Dalvik.vm.headgrowthlimit =96m" means that a single process heap memory is limited to 96m, the program will actually only use 96m of memory when it runs.

If the requested memory resource exceeds the above limit, the system throws an oom error.

4, common measures to avoid oom

The following mainly summarizes the common measures from four aspects: 1) Reduce the memory consumption of objects, 2) the reuse of memory objects, 3) avoid the memory leakage of objects; 4) Memory Usage policy optimization.

4.1 Reducing the memory footprint of an object

    • Use Arraymap/sparsearray instead of traditional data structures such as HashMap.
      • Reference link: Android Memory optimizer (use Sparsearray and arraymap instead of HashMap)
    • Avoid using enumerations in Android.
    • Reduces the memory footprint of the bitmap object. Insamplesize and decode format.

4.2 Re-use of memory objects

    • Listview/gridview, such as a large number of duplicate sub-components of the view inside the Convertview reuse
    • Caching bitmap using the LRU mechanism
    • Avoid performing object creation in the OnDraw method
    • Use StringBuilder to replace frequent "+"

4.3 Avoiding memory leaks for objects

Both 4.1 and 4.2 are more conventional measures and 4.3 need to be focused.

1) Activity leaks

There are a number of reasons for activity leaks, and some of the more common ones are listed below. The main principles are divided into two categories:i) static objects; ii) this$0.

  • Activity is referenced by the static variable. This code is from ourCrash upload
    Private StaticMap<componentname, exceptionhandler> configmap =NewHashmap<componentname, exceptionhandler>(); Public Static voidSetactivity (FinalActivity activity,Booleansend2server) {LOG.D (TAG,"Bind exception handler:" +activity.getcomponentname (). GetClassName ()); //Context InitializationSdkcontext.init (Activity.getapplication ());    Init (Activity.getapplication ()); Exceptionhandler Exceptionhandler=NewExceptionhandler (activity, Send2server, Thread.getdefaultuncaughtexceptionhandler ());    Configmap.put (Activity.getcomponentname (), Exceptionhandler); Thread.setdefaultuncaughtexceptionhandler (Exceptionhandler);}

The following is an activity leak through mat analysis :

    • Internal class references result in activity leaks
      The most typical scenario is an activity leak caused by handler, and if there are deferred tasks in handler or if the queue of tasks waiting to be executed is too long, it is possible that the activity will leak because handler continues to execute. The reference chain at this time is Activity, Handler, Message, MessageQueue, Looper. To solve this problem, you can execute the message in the Remove handler message queue with the Runnable object before the UI exits. or use static + WeakReference to achieve a referential relationship between the disconnected handler and the activity.
      Reference Links: Thread communication

2) Consider using application context instead of activity context

For most situations where the activity context is not required (the context of dialog must be the activity context), we can all consider using application context instead of the activity context , so you can avoid inadvertent activity leaks.

3) Pay attention to the timely recovery of temporary bitmap objects

While in most cases we will increase the caching mechanism for bitmap, some of the bitmap need to be reclaimed in a timely manner. For example, a relatively large bitmap object that was created temporarily, after being transformed to get a new bitmap object, should reclaim the original bitmap as soon as possible, so that the space occupied by the original bitmap can be released faster.

4) Memory Footprint monitoring
The maxmemory is obtained through the runtime, while Maxmemory-totalmemory is the remaining Dalvik memory that can be used. Check this value regularly to 80% to release the cache resources (bitmap cache).

/*** Returns The maximum number of bytes the heap can expand to. See {@link#totalMemory} for the * Current number of bytes taken by the heap, and {@link#freeMemory} for the current number of * Those bytes actually used by live objects. */intMaxMemory = Runtime.getruntime (). MaxMemory ());//Maximum available memory for the application/*** Returns the number of bytes taken by the heap at its current size. The heap may expand or * contract over time, as the number of live objects increases or decreases. See * {@link#maxMemory} for the maximum heap size, and {@link#freeMemory} for a idea of how much * The heap could currently contract. */LongTotalMemory = Runtime.getruntime (). TotalMemory ());//application has acquired memory/*** Returns The number of bytes currently available on the heap without expanding the heap. See * {@link#totalMemory} for the heap ' s current size. When these bytes is exhausted, the heap * may expand. See {@link#maxMemory} for that limit. */LongFreememory = Runtime.getruntime (). Freememory ());//application has acquired unused memory in memory

5) Note whether the cursor object is closed in time

In the program we often do the query database operation, but there are often inadvertently use the cursor after the case is not closed in a timely manner. These cursor leaks, repeated occurrences of the words will have a great negative impact on memory management, we need to remember to close the cursor object in a timely manner.

4.4 Memory Usage Policy optimization

    • Use large heap sparingly
    • Comprehensive consideration of device memory thresholds and other factors design appropriate cache size
    • Onlowmemory ()/ontrimmemory (int)
    • Resource files need to choose the right folder to store
    • Try catch operation of some large memory allocations
    • Use static objects with caution
    • Optimize layout hierarchies and reduce memory consumption
    • Use multiple processes with caution
    • Use the Dependency Injection framework sparingly
    • Use Proguard to weed out unwanted code
    • Cautious use of third-party libraries
    • Consider different implementations to optimize memory consumption
Two, thread safety 1, the following method is thread-safe?
class MyCounter {    privatestaticint counter = 0;      Public Static int GetCount () {        return counter++;    }}

How to make the above method thread-safe?
2. Thread safety in Java

How to maintain data consistency in a multithreaded environment, Java provides a variety of ways to achieve:

    1. Synchronized
    2. Java.util.concurrent.atomic
    3. Java.util.concurrent.locks
    4. Thread Safe Collection (CONCURRENTHASHMAP)
    5. Volatile

2.1 Synchronized

The JVM guarantees that code snippets that are modified by the Synchronized keyword can be accessed by only one thread at a time, internally by locking the object or class . When the method is synchronized modified, the lock is added to the object, and when the method is static, the lock is added to the class. From a performance standpoint, it is generally not recommended to add locks directly to the class, which makes the method of all objects of the class synchronized.

Judging from the previous scan, there are two main points to note when writing a synchronized program:

    • Synchronized need to create locks based on objects or classes, so you cannot lock on constructors or variables.
    • Synchronized cause a deadlock.

1) where is the lock added?

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(Resultpoint point:currentpossible) {canvas.drawcircle (Frameleft+ (int) (Point.getx () *ScaleX), Frametop+ (int) (Point.gety () *ScaleY), point_size, paint); }    }}

In the above method, the creation of possibleresultpoints does not take synchronization measures and requires the use of collections.synchronizedxxx.

list<mytype> list = collections.synchronizedlist (new ArrayList (<MyType>)); synchronized (list) {    for(MyType m:list) {        foo (m);        M.dosomething ();    }}

General comparison It is recommended to create a virtual object specifically for acquiring locks.
// Dummy object variable for synchronization Private Object mutex=New  object (), ... . // using synchronized block to read, increment and update count value synchronously synchronized (Mutex) {        count+ +;}

PS: Directly on the method add synchronized possible Dos attack Oh, give a chestnut:

 Public classMyObject {//Locks on the object ' s monitor     Public synchronized voiddosomething () {// ...    }}//Code of the hackerMyObject MyObject =NewMyObject ();synchronized(myObject) { while(true) {        //indefinitely delay MyObjectThread.Sleep (Integer.max_value); }}

The hacker's code acquires a lock on the MyObject object, causing the dosomething to deadlock, thus triggering the denial of Service.

 Public classMyObject {//locks on the class object ' s monitor     Public Static synchronized voiddosomething () {// ...    }}//Code of the hackersynchronized(MyObject.class) {     while(true) {thread.sleep (integer.max_value);//indefinitely delay MyObject    }}

2) deadlock.

 Public classThreaddeadlock { Public Static voidMain (string[] args)throwsinterruptedexception {Object obj1=NewObject (); Object Obj2=NewObject (); Object obj3=NewObject (); Thread T1=NewThread (NewSyncthread (Obj1, Obj2), "T1"); Thread T2=NewThread (NewSyncthread (Obj2, obj3), "T2"); Thread T3=NewThread (NewSyncthread (Obj3, obj1), "T3");        T1.start (); Thread.Sleep (5000);        T2.start (); Thread.Sleep (5000);    T3.start (); }}classSyncthreadImplementsrunnable{PrivateObject obj1; PrivateObject Obj2;  PublicSyncthread (Object O1, Object O2) { This. obj1=O1;  This. obj2=O2; } @Override Public voidrun () {String name=Thread.CurrentThread (). GetName (); SYSTEM.OUT.PRINTLN (Name+ "acquiring lock on" +obj1); synchronized(obj1) {System.out.println (name+ "acquired lock on" +obj1);         Work (); SYSTEM.OUT.PRINTLN (Name+ "acquiring lock on" +obj2); synchronized(obj2) {System.out.println (name+ "acquired lock on" +obj2);        Work (); } System.out.println (Name+ "released lock on" +obj2); } System.out.println (Name+ "released lock on" +obj1); SYSTEM.OUT.PRINTLN (Name+ "finished execution."); }    Private voidWork () {Try{Thread.Sleep (30000); } Catch(interruptedexception e) {e.printstacktrace (); }    }}

What does the above code output?

Android Development notes-memory leaks and thread safety for common bug types

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.