안드로이드 성능 최적화 : 알리, 텐센트와 메모리 누수에 대한 다른 지식은 여기에 있습니다!

그렇지 않으면 그것을 찾을 수 없습니다, 모음 추천! ! !

머리말

안드로이드에서 메모리 누수 현상이 공통적으로하고, 결과를 결과 메모리 누수가이 논문 메모리 누수, 이유 및 솔루션, 궁극적으로 일반적인 메모리 누수 분석 도구를 제공하는 특성을 종합적으로 소개 응용 프로그램 충돌을 만들 것입니다, 그것을 좋아하길 바랍니다.

디렉토리

영상

1. 소개

ML (메모리 누수)의 메모리를 사용할 필요는 없지만 및 발표 프로그램으로 리턴 할 수없는 응용 프로그램 메모리의 현상을 의미하는 것이

응용 프로그램의 2에 미치는 영향

쉬운 응용 프로그램 메모리 오버 플로우, 그 OOM 메모리 오버 플로우 설명을 만들려면 :

안드로이드 성능 최적화 : 알리, 텐센트와 메모리 누수에 대한 다른 지식은 여기에 있습니다!

3. 메모리 누수의 원인의 본질은 발생

구체적인 설명

안드로이드 성능 최적화 : 알리, 텐센트와 메모리 누수에 대한 다른 지식은 여기에 있습니다!

  • 기구의 관점에서 특별한주의 자바 쓰레기 수집합니다 (GC)의 존재는, 메모리 누출이 존재하지 않아야하기 때문에, 메모리 누수가 발생하기 때문에 예기치 않은 개체 참조 이러한 기준에 의해 유지 만 외부지지 인간 원인 = 라이프 사이클>의 참조 수명주기

4. 기술 자료 : 안드로이드 메모리 관리 메커니즘

4.1 소개

안드로이드 성능 최적화 : 알리, 텐센트와 메모리 누수에 대한 다른 지식은 여기에 있습니다!

다음에, 회복 과정, 오브젝트 메모리 할당, 가변 및 재활용 상세히 설명해

메모리 전략의 프로세스 4.2 . 프로세스 공간이 꽉 때, 그것은 것, 안드로이드 과정에서 복구 응용 프로그램 프레임 워크 결정 과정 유형 호스팅 : 중앙 ActivityManagerService에 의한 메모리 할당 전략은 메모리 복구 전략 1 단계 (B) 모든 프로세스에 대한 메모리 할당을 관리 할 수 있습니다. 낮은 우선 순위에 따라 처리 - >> 높은 순서대로 자동 복구 프로세스 안드로이드 다섯 개 가지 우선 순위 수준에 과정은 다음과 같습니다 :

안드로이드 성능 최적화 : 알리, 텐센트와 메모리 누수에 대한 다른 지식은 여기에 있습니다!

2 단계 : 모든 프로세스 (변수 형용사에 저장 점수) 리눅스 커널 리눅스 커널을 업데이트 점수 리눅스 커널 실제 복구 프로세스 ActivityManagerService의 특정 점수는 실제 메모리 복구에 의해 이루어집니다

여기 과정을 복잡하게 만 프로세스를 요약, 관심있는 독자는 시스템의 소스 코드 ActivityManagerService.java를 연구 할 수

객체, 변수, 메모리 전략 4.2

  • 자바와 안드로이드에 대한 객체, 변수, 메모리 전략
  • = 메모리 할당 메모리 관리 객체 / 가변 할당 해제 +

아래, 우리는 더 많은 메모리 해제 메모리 할당 및 전략 a를 이야기 할 것이다. 메모리 할당 전략을

  • 메모리 할당 개체 / 프로그램의 변수 자동 책임
  • 3 종류가있다 : 정적 분포는 아래에 설명 된 정적 변수, 로컬 변수 및 오브젝트, 예를 들어 각각의 스택, 힙 분배 및 분배

안드로이드 성능 최적화 : 알리, 텐센트와 메모리 누수에 대한 다른 지식은 여기에 있습니다!

참고 : 메모리 할당 예를 설명하는 데 사용

public class Sample {    
    int s1 = 0;
    Sample mSample1 = new Sample();   

    // 方法中的局部变量s2、mSample2存放在 栈内存
    // 变量mSample2所指向的对象实例存放在 堆内存
      // 该实例的成员变量s1、mSample1也存放在栈中
    public void method() {        
        int s2 = 0;
        Sample mSample2 = new Sample();
    }
}
    // 变量mSample3所指向的对象实例存放在堆内存
    // 该实例的成员变量s1、mSample1也存放在堆内存中
    Sample mSample3 = new Sample();

나. 메모리 출시 전략

  • 메모리 해제 개체 / 변수는 자바 가비지 컬렉터 (GC) / 스택 프레임의 책임
  • 여기서 주로 (인 힙 할당 식) 목표 분배 메모리 분리 전략 = 자바 가비지 컬렉터 (GC)

자동 분배 비교적 단순하고, 따라서 상세한 설명은 생략 스택 프레임 만, 스택을 스택 방출없이 정적 할당 보낸

  • 자바 가비지 컬렉터 (GC) 메모리 방출 = 가비지 컬렉션 알고리즘을 포함 :

안드로이드 성능 최적화 : 알리, 텐센트와 메모리 누수에 대한 다른 지식은 여기에 있습니다!

아래에 설명

안드로이드 성능 최적화 : 알리, 텐센트와 메모리 누수에 대한 다른 지식은 여기에 있습니다!

5. 일반적인 메모리 누수 및 솔루션의 원인

메모리에 공통 리드 주된 이유 누수 :

  1. 컬렉션
  2. 정적 멤버 변수 키워드 변형
  3. 비 정적 내부 클래스 / 익명 클래스
  4. 자원 객체는 사용 후 닫혀 있지 않습니다

다음, I 의지 세부 왜 각 트리거 메모리 누수

5.1 컬렉션

  • 메모리 요소를 추가 한 후, 정지 물체를 일으키는 것이 보여 메모리 누수 예 초래 재활용 될 수없는 요소들의 집합이며, 수집 소자 개체 이유 모음 누설 참조 :
// 通过 循环申请Object 对象 & 将申请的对象逐个放入到集合List
List<Object> objectList = new ArrayList<>();        
       for (int i = 0; i < 10; i++) {
            Object o = new Object();
            objectList.add(o);
            o = null;
        }
// 虽释放了集合元素引用的本身:o=null)
// 但集合List 仍然引用该对象,故垃圾回收器GC 依然不可回收该对象
  • 솔루션 컬렉션 클래스는 요소의 컬렉션을 추가 한 후 객체는 사용 후 컬렉션에서 제거해야합니다

요소들의 세트 수 있기 때문에 가장 쉬운 방법은 비우는 = 컬렉션 오브젝트는 널 (null)로 설정되어 있으므로

 // 释放objectList
        objectList.clear();
        objectList=null;

5.2 정적 부재 변수 키워드 수정

  • 지식의 라이프 사이클 예비 응용 프로그램 수명주기의 키워드 정적 멤버 변수 = 수정한다
  • Ruoshi 정적 자원 (예 컨텍스트와 같은)의 과도한 소비의 멤버 변수 인스턴스를 변형되는 키워드들 누설 이유는, 그 멤버 변수의 수명 경향 경우> 인용 인스턴스 수명은 인스턴스들 때 파괴 수명의 끝 될 그 메모리 누출이 예를 들어 설명하고이 발생하므로,이 때문에, 정적 변수를 유지하고 복구 할 수있다 :
public class ClassName {
 // 定义1个静态变量
 private static Context mContext;
 //...
// 引用的是Activity的context
 mContext = context; 

// 当Activity需销毁时,由于mContext = 静态 & 生命周期 = 应用程序的生命周期,故 Activity无法被回收,从而出现内存泄露
}
  • 솔루션
  1. 피하려고 부재 정적 변수 (예 컨텍스트와 같은) 리소스의 과다한 소비 인스턴스들

참조 컨텍스트의 컨텍스트 Applicaiton을 사용하려고

  1. 강한 장소 참고 예에 유지하여 약 참조 (WeakReference를)

주 : 고정 부재 변수 대표적인 = 싱글 거기

  • 예비 정적 특성 이후 지식 싱글, 애플리케이션 라이프 사이클의 수명주기의 길이 =
  • 누출 원인 개체가 단일 실시 형태는 객체에 대한 객체 참조를 보유 사용할 필요가없는 경우, 오브젝트는 적절하게 메모리 누수 발생 회수 할 수 없습니다

프리젠 테이션의 예 :

// 创建单例时,需传入一个Context
// 若传入的是Activity的Context,此时单例 则持有该Activity的引用
// 由于单例一直持有该Activity的引用(直到整个应用生命周期结束),即使该Activity退出,该Activity的内存也不会被回收
// 特别是一些庞大的Activity,此处非常容易导致OOM

public class SingleInstanceClass {    
    private static SingleInstanceClass instance;    
    private Context mContext;    
    private SingleInstanceClass(Context context) {        
        this.mContext = context; // 传递的是Activity的context
    }  

    public SingleInstanceClass getInstance(Context context) {        
        if (instance == null) {
            instance = new SingleInstanceClass(context);
        }        
        return instance;
    }
}
  • 객체 참조 응용 프로그램 수명주기 싱글 라이프 사이클 솔루션 =

위의 예에서, 애플리케이션은, 애플리케이션의 생존 구간 = 때문에 애플리케이션 라이프 사이클을 컨텍스트를 전송해야

public class SingleInstanceClass {    
    private static SingleInstanceClass instance;    
    private Context mContext;    
    private SingleInstanceClass(Context context) {        
        this.mContext = context.getApplicationContext(); // 传递的是Application 的context
    }    

    public SingleInstanceClass getInstance(Context context) {        
        if (instance == null) {
            instance = new SingleInstanceClass(context);
        }        
        return instance;
    }
}

5.3 비 정적 내부 클래스 / 익명 클래스

  • 예약 비 정적 내부 클래스 지식 / 기본 익명 클래스는 외부 클래스에 대한 참조를 보유하고, 정적 내부 클래스는 아니다
  • 일반적인 경우 3 종류 즉 : 비 정적 내부 클래스 = 정적 멀티 스레드 메시지 전달기구로서는 (핸들러)

비 정적 정적 내부 클래스의 예 5.3.1 =

  • 그렇지 않으면하여 만든 원인 정적 내부 클래스의 인스턴스를 공개 = 정적 (응용 프로그램 수명주기 = 라이프 사이클은) 결국 메모리 누수로 이어지는 해제 할 수 없습니다 때문에 외부 클래스에 의한 비 정적 내부 클래스를 외부 클래스의 기본에 대한 참조를 개최합니다

즉, 외부 클래스 유지 정적 비 정적 내부 클래스 객체를 보여주는 예이다 :

// 背景:
   a. 在启动频繁的Activity中,为了避免重复创建相同的数据资源,会在Activity内部创建一个非静态内部类的单例
   b. 每次启动Activity时都会使用该单例的数据

public class TestActivity extends AppCompatActivity {  

    // 非静态内部类的实例的引用
    // 注:设置为静态  
    public static InnerClass innerClass = null; 

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);   

        // 保证非静态内部类的实例只有1个
        if (innerClass == null)
            innerClass = new InnerClass();
    }

    // 非静态内部类的定义    
    private class InnerClass {        
        //...
    }
}

// 造成内存泄露的原因:
    // a. 当TestActivity销毁时,因非静态内部类单例的引用(innerClass)的生命周期 = 应用App的生命周期、持有外部类TestActivity的引用
    // b. 故 TestActivity无法被GC回收,从而导致内存泄漏
  • 솔루션
  1. 설정 비 정적 내부 클래스 : 정적 내부 클래스 (정적 내부 클래스는 기본 참조를 외부 클래스를 개최하지 않음)
  2. 하나의 패키지 형태로 추출 내부 클래스
  3. 비 정적 내부 클래스는 인스턴스를 생성하지 않도록하십시오 = 정적

사용 상황, 상황에의 적용을 권장

5.3.2 다중 스레딩 : AsyncTask를, Runnable를 구현, 스레드 클래스 상속

  • 사용 지식 멀티 스레드 예약은 비 정적 내부 클래스 / 익명 클래스를 =, 즉 클래스는 비 정적 내부 클래스 / 익명 클래스입니다 스레드
  • 작업자 스레드 누설 이유는 처리 작업 및 외부 클래스 메모리 누수로 인한 재활용 할 수없는 외부 클래스 가비지 컬렉터 (GC)를 허용 할 외부 레퍼런스를 보유 인해 작업자 클래스로 파괴 될 때

멀티 스레딩의 주요 사용은 다음과 같습니다 AsyncTask를이 주로 예를 들어 여기 Thread 클래스를 상속하기 위해, Runnable를 구현 및 스레드 클래스 3의 메모리 누수 이전과 동일한 원리를 상속

프리젠 테이션의 예

/** 
     * 方式1:新建Thread子类(内部类)
     */  
        public class MainActivity extends AppCompatActivity {

        public static final String TAG = "carson:";
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // 通过创建的内部类 实现多线程
            new MyThread().start();

        }
        // 自定义的Thread子类
        private class MyThread extends Thread{
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Log.d(TAG, "执行了多线程");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

   /** 
     * 方式2:匿名Thread内部类
     */ 
     public class MainActivity extends AppCompatActivity {

    public static final String TAG = "carson:";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 通过匿名内部类 实现多线程
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Log.d(TAG, "执行了多线程");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }.start();
    }
}

/** 
  * 分析:内存泄露原因
  */ 
  // 工作线程Thread类属于非静态内部类 / 匿名内部类,运行时默认持有外部类的引用
  // 当工作线程运行时,若外部类MainActivity需销毁
  // 由于此时工作线程类实例持有外部类的引用,将使得外部类无法被垃圾回收器(GC)回收,从而造成 内存泄露
  • 솔루션은 메모리 누수 원인 두 가지 중요한 조건이, 위의에서 볼 수있다 :
  1. 이 사이의 관계를 참조 인 "노동 계급 외부 스레드 인스턴스에 대한 참조를 보유"
  2. 외부 클래스 솔루션은 위의 조건 중 하나를 충족하지 않도록한다는 생각 = 1을 파괴 할 필요가있는 동안 작업자 스레드 인스턴스> 외부 클래스 수명주기의 라이프 사이클은, 그 작업자 스레드는 계속 실행됩니다.
// 共有2个解决方案:静态内部类 & 当外部类结束生命周期时,强制结束线程
// 具体描述如下

   /** 
     * 解决方式1:静态内部类
     * 原理:静态内部类 不默认持有外部类的引用,从而使得 “工作线程实例 持有 外部类引用” 的引用关系 不复存在
     * 具体实现:将Thread的子类设置成 静态内部类
     */  
        public class MainActivity extends AppCompatActivity {

        public static final String TAG = "carson:";
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // 通过创建的内部类 实现多线程
            new MyThread().start();

        }
        // 分析1:自定义Thread子类
        // 设置为:静态内部类
        private static class MyThread extends Thread{
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Log.d(TAG, "执行了多线程");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

   /** 
     * 解决方案2:当外部类结束生命周期时,强制结束线程
     * 原理:使得 工作线程实例的生命周期 与 外部类的生命周期 同步
     * 具体实现:当 外部类(此处以Activity为例) 结束生命周期时(此时系统会调用onDestroy()),强制结束线程(调用stop())
     */ 
     @Override
    protected void onDestroy() {
        super.onDestroy();
        Thread.stop();
        // 外部类Activity生命周期结束时,强制结束线程
    }

5.3.3 메시지 전달기구 : HandlerAndroid 메모리 누수 : 세부 이유로 솔루션 처리기 메모리 누출 https://www.jianshu.com/p/031515d8a7ca

5.4 자원 객체는 사용 후 닫혀 있지 않습니다

  • 이러한 자원의 활동 적시 폐쇄 / 취소를 파괴하지 않는 경우 (예 : 라디오 BraodcastReceiver, 파일 스트림 파일, 커서 커서 데이터베이스, 비트 맵 이미지 자료 등) 자원의 사용에 대한 이유를 공개, 이러한 리소스는 메모리의 결과로 복구되지 않습니다 누출
  • 솔루션 파괴 할 때 자원의 활동 적시 폐쇄 / 취소
// 对于 广播BraodcastReceiver:注销注册
unregisterReceiver()

// 对于 文件流File:关闭流
InputStream / OutputStream.close()

// 对于数据库游标cursor:使用后关闭游标
cursor.close()

// 对于 图片资源Bitmap:Android分配给图片的内存只有8M,若1个Bitmap对象占内存较多,当它不再被使用时,应调用recycle()回收此对象的像素所占用的内存;最后再赋为null 
Bitmap.recycle();
Bitmap = null;

// 对于动画(属性动画)
// 将动画设置成无限循环播放repeatCount = “infinite”后
// 在Activity退出时记得停止动画

5.5 다른 사용

  • 이러한 네 가지 일반적인 상황, 어떤 일상적인 사용뿐만 아니라 메모리 누수로 이어질 수
  • 포함 : 컨텍스트, 웹보기, 어댑터, 아래에 설명

영상

5.6 요약 내가지도 및 솔루션과 안드로이드 메모리 누수에 대한 이유를 요약합니다 아래

메모리 누수 6. 도구를 이용한 분석

  • 심지어 완전히 메모리 누수의 원인을 이해하지만, 필연적으로 메모리 누수 또는 현상이있을 것
  • 다음은 누출 도구가 주류 메모리의 일부에 대한 간략한 분석입니다
  1. MAT (메모리 분석 도구)
  2. 힙 뷰어
  3. 할당 추적기
  4. 안드로이드 스튜디오 的 메모리 모니터
  5. LeakCanary

6.1 MAT (메모리 분석 도구)

  • 정의 : 이클립스 자바 힙 메모리 분석 도구 - >> 다운로드
  • 역할 : 현재 메모리 사용량보기

신속 자바 프로세스 HPROF 분석 메모리 스냅 샷을 분석함으로써 물체 가비지에 의해 수집 될 수 없다 및 이러한 결과의 원인이 물체를 직관적으로 보아 확인할 수있는 참조 메모리 풋 프린트 크기의 물체를 계산할

특정 사용 : MAT 사용 해적

6.2 힙 뷰어

정의 : 자바 힙 메모리 분석 도구 역할의 :보기 현재 메모리 스냅 샷

힙 메모리는 데이터 및 데이터 유형을 다른 유형의 총 비율을 개별적으로 볼 수있다

특정 사용 : 힙 뷰어를 사용하여 해적

6.3 할당 추적기

소개 : 추적 메모리 효과 분석 도구 : 할당 추적기 해적을 사용 : 메모리 할당 정보, 시퀀스의 특정 사용을 추적

6.4 메모리 모니터

설명 : 안드로이드 스튜디오는 메모리 효과를 감지 할 수있는 그래픽 도구와 함께 제공 : 시스템 / 메모리 사용 응용 프로그램을 추적. 핵심 기능은 다음이다

영상

특정 사용 : 안드로이드 Studio는 메모리 모니터 해적을 사용하는

6.5 LeakCanary

설명 : 사각형 안드로이드 오픈 소스 라이브러리를 생성 - 다운로드 역할 >> : 메모리를 감지하는 특정 사용을 누설 : https://www.liaohuqiu.net/cn/posts/leak-canary/

7. 요약

이 문서에서는 메모리 누수, 이유 및 솔루션의 포괄적 인 성격, 당신이 개발에 메모리 누수를 피하려고 희망을 설명합니다

이 문서를 좋아하거나 도움말을 당신이 앞으로주의 오 엄지 손가락을 많이 희망하는 경우 기사는 쉬운 일이 아니다. 기사는 지속적으로 업데이트됩니다. 물론 건조! ! !

추천

출처blog.51cto.com/14775360/2484779