Android Development notes & mdash; common BUG types: Memory leakage and thread security, androidbug

Source: Internet
Author: User

Android Development notes-Memory leakage and thread security of common BUG types, androidbug

 

The content of this article comes from the summary of the last internal sharing and cannot be detailed. Sorry.

This article focuses onMemory leakageAndThread SecurityThese two problems are explained. The bugs detected by internal code scanning are roughly divided into four categories: 1) NULL pointer; 2) Division of 0; 3) memory and resource leakage; 4) thread security. The first and second problems are not considered weekly. The third and fourth problems require more in-depth analysis. 1. Memory leakage 1. Sorry, "XXX" has stopped running. OOM?

How can an app report OOM? The simplest method is as follows:

Bitmap bt1 = BitmapFactory.decodeResource(this.getResources(), R.drawable.image);Bitmap bt2 = BitmapFactory.decodeResource(this.getResources(), R.drawable.image);Bitmap btn = ...
2. view memory usage
  • Command Line: adb shell dumpsys meminfoPackageName

  • View the Real-Time Changes of Dalvik Heap in Memory using the Memory Monitor of Android Studio

3. Conditions for Memory leakage

First, each app has a maximum memory limit.

ActivityManager activityManager = (ActivityManager) context.getSystemServiceContext.ACTIVITY_SERVICE);activityManager.getMemoryClass();
 
GetMemoryClass () obtains the maximum memory resource. Heap memory in Android is divided into Native Heap and Dalvik Heap. C/C ++ applied for memory space in Native Heap, and Java applied for memory space in 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

Note:

The heapsize parameter indicates the maximum memory available for a single heap process. However, if the following parameter exists: "dalvik. vm. headgrowthlimit = 96m "indicates that the heap memory of a single process is limited to 96 MB, that is, the program runs only 96 MB of memory.

If the applied memory resource exceeds the above limit, the system will throw an OOM error.

4. Common Measures to Avoid OOM

The following measures are summarized from four aspects: 1) Reduce the memory usage of objects; 2) Reuse of memory objects; 3) avoid Memory leakage of objects; 4) memory usage policy optimization.

4.1 Reduce the memory usage of Objects

  • Use ArrayMap/SparseArray instead of HashMap and other traditional data structures.
    • Reference link: Android memory optimization (replacing HashMap with SparseArray and ArrayMap)
  • Do not use enumeration in Android.
  • Reduces the memory usage of Bitmap objects. InSampleSize and decode format.

4.2 reuse of memory objects

  • Reuse of ConvertView in views with a large number of repeated child components such as ListView and GridView
  • Use the LRU mechanism to cache Bitmap
  • Avoid creating objects in the onDraw Method
  • Use StringBuilder to replace frequent "+"

4.3 avoid Memory leakage of Objects

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

1) Activity Leakage

There are many causes of Activity leakage. The following lists some common causes. There are two main categories in principle:I) static object; ii) this $0.

  • Activity is referenced by static variables. This Code comes from ourCrash upload
    Private static Map <ComponentName, ExceptionHandler> configMap = new HashMap <ComponentName, ExceptionHandler> (); public static void setActivity (final Activity activity, boolean send2Server) {Log. d (TAG, "bind exception handler:" + activity. getComponentName (). getClassName (); // context initialization SDKContext. init (activity. getApplication (); init (activity. getApplication (); ExceptionHandler exceptionHandler = new ExceptionHandler (activity, send2Server, Thread. getDefaultUncaughtExceptionHandler (); configMap. put (activity. getComponentName (), exceptionHandler); Thread. setDefaultUncaughtExceptionHandler (exceptionHandler );}

Below isMAT AnalysisLeaked by an Activity:
 

  • Internal class reference causes Activity Leakage
    The most typical scenario is the Activity leakage caused by Handler. If there are delayed tasks in Handler or the queue of tasks waiting for execution is too long, the Activity leakage may occur because the Handler continues to execute. In this case, the reference link isLogoff-> MessageQueue-> Message-> Handler-> Activity. To solve this problem, you can execute remove the message and runnable object in the Handler message queue before the UI exits. Or use Static + WeakReference to disconnect the reference relationship between Handler and Activity.
    Reference link: thread Communication

2) Consider using Application Context instead of Activity Context.

For most cases where the Activity Context is not required (the Dialog Context must be the Activity Context), we can consider using the Application Context instead of the Activity Context to avoid accidental Activity leakage.

3) Pay attention to timely collection of temporary Bitmap objects

Although in most cases, we will add a caching mechanism for Bitmap, some Bitmap needs to be recycled in a timely manner. For example, if a relatively large bitmap object is created temporarily, the original bitmap should be recycled as soon as possible after the new bitmap object is transformed, so that the space occupied by the original bitmap can be quickly released.

4) monitor memory usage
MaxMemory is obtained through Runtime, while maxMemory-totalMemory is the remaining available dalvik memory. Check this value regularly to release various cache resources (bitmap cache) when it reaches 80% ).

/*** Returns the maximum number of bytes the heap can expand. 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. */int maxMemory = Runtime. getRuntime (). maxMemory (); // maximum available memory of 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 an idea of how much * the heap cocould currently contract. */long totalMemory = Runtime. getRuntime (). totalMemory (); // the application has obtained the 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 are exhausted, the heap * may expand. see {@ link # maxMemory} for that limit. */long freeMemory = Runtime. getRuntime (). freeMemory (); // The application has obtained the memory in use.

5) check whether the Cursor object is closed in time

In the program, we often perform database query operations, but there are often situations where the Cursor is not closed in time due to carelessness. The leakage of these Cursor results in a significant negative impact on memory management if it appears multiple times. We need to remember to close the Cursor object in time.

4.4 memory usage policy optimization

  • Use large heap with caution
  • Design a suitable cache Size Based on the device memory threshold and other factors
  • OnLowMemory ()/onTrimMemory (int)
  • Select a suitable folder for storing resource files.
  • Try catch some large Memory Allocation Operations
  • Exercise caution when using static objects
  • Optimize layout layers to reduce memory consumption
  • Use multiple processes with caution
  • Use the dependency injection framework with caution
  • Use ProGuard to remove unnecessary code
  • Exercise caution when using third-party libraries
  • Consider different implementation methods to optimize memory usage
Ii. Thread Security 1. Are the following methods thread-safe?
class MyCounter {    private static int counter = 0;    public static int getCount() {        return counter++;    }}

How to Ensure the thread security of the above method?
 
2. thread security in Java

Java provides multiple methods to maintain data consistency in a multi-threaded environment:

2.1 synchronized

JVM ensures that the code segment Modified by the synchronized keyword can only be accessed by one thread at a time.ObjectOrClassLock. When the method is modified by synchronized, the lock is added to the object; when the method is static at the same time, the lock is added to the class. From the performance perspective, it is generally not recommended to add the lock to the class directly, so that the method of all objects in the class is synchronized.

From the perspective of previous scans, there are two main points to note when writing a synchronized program:

  • Synchronized requires the creation of Object-based or class-based locks, so the locks cannot be applied to constructors or variables.
  • Synchronized causes a deadlock.

1) Where is the lock applied?

List<ResultPoint> currentPossible = possibleResultPoints;List<ResultPoint> currentLast = lastPossibleResultPoints;int frameLeft = frame.left;int frameTop = frame.top;if (currentPossible.isEmpty()) {    lastPossibleResultPoints = null;} else {    possibleResultPoints = new ArrayList<>(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 possibleResultPoints creation does not adopt synchronization measures, so you need to useCollections. synchronizedXxx.

List<MyType> list = Collections.synchronizedList(new ArrayList(<MyType>));...synchronized(list){    for(MyType m : list){        foo(m);        m.doSomething();    }}

We generally recommend that you create a virtual object to obtain the lock.
//dummy object variable for synchronizationprivate Object mutex=new Object();...//using synchronized block to read, increment and update count value synchronouslysynchronized (mutex) {        count++;}

PS: Adding synchronized directly to the method may cause DoS attacks. For example:

Public class MyObject {// Locks on the object's monitor public synchronized void doSomething (){//...}} // Hacker code MyObject myObject = new MyObject (); synchronized (myObject) {while (true) {// Indefinitely delay myObject Thread. sleep (Integer. MAX_VALUE );}}

The hacker's Code acquires the lock of the MyObject object, resulting in a doSomething deadlock and causing Denial of Service.

Public class MyObject {// locks on the class object's monitor public static synchronized void doSomething (){//...}} // Hacker code synchronized (MyObject. class) {while (true) {Thread. sleep (Integer. MAX_VALUE); // Indefinitely delay MyObject }}

2) deadlock.

public class ThreadDeadlock {    public static void main(String[] args) throws InterruptedException {        Object obj1 = new Object();        Object obj2 = new Object();        Object obj3 = new Object();        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");        Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");        t1.start();        Thread.sleep(5000);        t2.start();        Thread.sleep(5000);        t3.start();    }}class SyncThread implements Runnable{    private Object obj1;    private Object obj2;    public SyncThread(Object o1, Object o2){        this.obj1=o1;        this.obj2=o2;    }    @Override    public void run() {        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 void work() {        try {            Thread.sleep(30000);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

What will the above Code output?

Related Article

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.