그렇지 않으면 그것을 찾을 수 없습니다, 모음 추천! ! !
머리말
안드로이드에서 메모리 누수 현상이 공통적으로하고, 결과를 결과 메모리 누수가이 논문 메모리 누수, 이유 및 솔루션, 궁극적으로 일반적인 메모리 누수 분석 도구를 제공하는 특성을 종합적으로 소개 응용 프로그램 충돌을 만들 것입니다, 그것을 좋아하길 바랍니다.
디렉토리
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. 일반적인 메모리 누수 및 솔루션의 원인
메모리에 공통 리드 주된 이유 누수 :
- 컬렉션
- 정적 멤버 변수 키워드 변형
- 비 정적 내부 클래스 / 익명 클래스
- 자원 객체는 사용 후 닫혀 있지 않습니다
다음, 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无法被回收,从而出现内存泄露
}
- 솔루션
- 피하려고 부재 정적 변수 (예 컨텍스트와 같은) 리소스의 과다한 소비 인스턴스들
참조 컨텍스트의 컨텍스트 Applicaiton을 사용하려고
- 강한 장소 참고 예에 유지하여 약 참조 (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回收,从而导致内存泄漏
- 솔루션
- 설정 비 정적 내부 클래스 : 정적 내부 클래스 (정적 내부 클래스는 기본 참조를 외부 클래스를 개최하지 않음)
- 하나의 패키지 형태로 추출 내부 클래스
- 비 정적 내부 클래스는 인스턴스를 생성하지 않도록하십시오 = 정적
사용 상황, 상황에의 적용을 권장
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:静态内部类
* 原理:静态内部类 不默认持有外部类的引用,从而使得 “工作线程实例 持有 外部类引用” 的引用关系 不复存在
* 具体实现:将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. 도구를 이용한 분석
- 심지어 완전히 메모리 누수의 원인을 이해하지만, 필연적으로 메모리 누수 또는 현상이있을 것
- 다음은 누출 도구가 주류 메모리의 일부에 대한 간략한 분석입니다
- MAT (메모리 분석 도구)
- 힙 뷰어
- 할당 추적기
- 안드로이드 스튜디오 的 메모리 모니터
- 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. 요약
이 문서에서는 메모리 누수, 이유 및 솔루션의 포괄적 인 성격, 당신이 개발에 메모리 누수를 피하려고 희망을 설명합니다
이 문서를 좋아하거나 도움말을 당신이 앞으로주의 오 엄지 손가락을 많이 희망하는 경우 기사는 쉬운 일이 아니다. 기사는 지속적으로 업데이트됩니다. 물론 건조! ! !