매일 한 개의 면접문제(제3기)---일반적으로 어떤 상황에서 메모리 유출 문제를 초래할 수 있습니까
메모리 누설
정의
방출되거나 쓸모없어야 할 대상은 다른 생존 대상이 인용을 가지고 있기 때문에 이 대상은 쓰레기 수거기에서 회수되지 못하고 메모리를 계속 차지하여 프로그램 실행을 느리게 하거나 붕괴시킨다.
까닭
왜 다른 생존 대상에게 인용을 가지고 있으면 회수할 수 없습니까?이것은 자바의 쓰레기 회수 메커니즘을 이해해야 한다.
java 쓰레기 회수 메커니즘
어떤 대상이 회수해야 한다고 여겨질까요?우리는 현재 모든 대상을 지향도의 결점으로 간주하고, 대상 간의 인용 관계는 지향도의 변이 있다.그러면 반드시 시작 결점 대상이 있을 것이다. 만약 이 대상이
추상적으로 말하자면, 한 프로그램에 이런 유방향도가 많이 존재할 것이다. 만약에 한 대상이 두 개의 시작 결점 대상이 존재하는 유방향도에 인용된다면.하나의 유방향도가 사명을 완수하려면 소각되어야 하지만, 다른 유방향도의 생명주기는 아직 끝나지 않았다.그러면 이 쓸모없어야 할 대상은 쓰레기 수거기에서 회수할 수 없고 다른 지향도 생명주기가 끝나야만 회수될 수 있다.
따라서 우리가 흔히 말하는 생명주기가 다른 두 대상 사이에 인용 관계가 있고 생명주기가 짧으면 메모리 유출을 초래할 수 있으며 지속 시간은 생명주기가 긴 대상에 달려 있다.만약 이 대상이 정적 변수라면, 프로그램 전체가 끝날 때까지 지속될 것입니다.
안드로이드 메모리 누출 상황
집합류
일반적인 집합 클래스는 메모리 유출을 일으키지 않지만 전체적인 집합 클래스라면 사용이 끝난 후remove 작업을 주의하지 않으면 메모리 유출을 초래할 수 있습니다.
단일 모드
여기서 단일 예제 모드는 만들 때 매개 변수로 Context를 입력해야 한다는 것을 말합니다.예를 들어 우리가 자주 쓰는 아래의 이 코드.public class Manager {
private static Manager instance;
private Context context;
private Manager(Context context){
this.context = context;
}
public static Manager getInstance(Context context){
if(instance == null){
instance = new Manager(context);
}
return instance;
}
}
관건은 이 Context에 있다. 만약에 이 Context가Activity의 Content라면 Activity의 생명주기와 단일 모드의 대상의 생명주기가 다르다는 것이 분명하다. Content에 전송된Activity가 사용되고 회수되어야 할 때 쓰레기 수거기에서 회수할 수 없다.
이 Context가 Application일 때 메모리 유출 문제가 존재하지 않는다는 것은 명백하다.단일 모드의 대상과 Application의 생명주기는 전체 응용의 생명주기이기 때문에 아무런 문제가 없다.
그래서 우리는 이렇게 쓸 수 있다public class Manager {
private static Manager instance;
private Context context;
private Manager(Context context){
this.context = context.getApplicationContext();
}
public static Manager getInstance(Context context){
if(instance == null){
instance = new Manager(context);
}
return instance;
}
}
물론 Application의 Context도 마음대로 사용할 수 있는 것은 아니다.Activity를 시작하려면 Application에서 새 Task 작업 스택을 만들어야 합니다.Dialog를 만들려면Activity의 context만 가능합니다.
익명 내부 클래스
익명 내부 클래스에 대해 안드로이드에서 전형적인 예는 핸들러죠.이것은 내가 1기에서 사용자 정의Handler가 메모리 유출을 어떻게 효과적으로 보장하는지 이미 분명하게 말했다.주로 익명 내부 클래스가 외부 클래스의 인용을 가지고 있기 때문에 익명 내부 클래스의 일부 조작으로 인해 이 내부 클래스 대상의 생명 주기와 외부 클래스의 생명 주기가 같지 않아 메모리 유출을 초래한다.
비정상 내부 클래스
개발 과정에서 우리는 프로그램의 효율과 자원의 중복 이용을 위해 이런 코드를 자주 쓸 수 있다.public class MainActivity extends BaseActivity {
private static Resource resource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(resource == null){
resource = new Resource();
}
}
class Resource{
}
}
이렇게 하면 자원의 중복 생성을 효과적으로 피할 수 있지만Activity가 시작될 때마다 이 자원을 신속하게 사용하지만 메모리 유출을 초래할 수 있다.비정상적인 내부 클래스도 기본적으로 외부 클래스의 인용을 가지고 있기 때문이다.이 비정상적인 내부 클래스의 정적 실례는 전체 응용 프로그램과 생명주기가 똑같이 길기 때문에 메모리 유출을 초래할 수 있다.
해결 방법은 이 내부 클래스를 정적 내부 클래스로 설정하거나 이 내부 클래스를 추출하여 하나의 단일 모델로 봉인하는 것이다.
자원이 닫히지 않았습니다.
Broadcast Receiver, File, Course,Stream,Content Observer 등 자원을 사용하거나 일부 프레임워크 이벤트bus 등에서 Register와 unRegister가 필요하다고 명확하게 표시할 때,Activity가 소각될 때 닫거나 취소해야 한다. 그렇지 않으면 이 자원들은 회수되지 않을 것이다.
불량 코드로 인한 압력
때때로 제때에 회수하지 못한 대상이 초래한 메모리 유출이 아니라 일부 코드가 필요하지 않은 메모리를 제때에 효과적으로 방출하지 않거나 기존 자원을 효과적으로 이용하지 못해 빈번하게 새로운 메모리를 신청하지 않아 메모리에 큰 압력을 가한다.
예를 들어ListView의ContentView는 ViewHolder의 유효한 복용 View를 사용하지 않고 빈번하게 새로운 View를 만들어서 메모리 압력을 발생시킨다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
public class Manager {
private static Manager instance;
private Context context;
private Manager(Context context){
this.context = context;
}
public static Manager getInstance(Context context){
if(instance == null){
instance = new Manager(context);
}
return instance;
}
}
public class Manager {
private static Manager instance;
private Context context;
private Manager(Context context){
this.context = context.getApplicationContext();
}
public static Manager getInstance(Context context){
if(instance == null){
instance = new Manager(context);
}
return instance;
}
}
public class MainActivity extends BaseActivity {
private static Resource resource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(resource == null){
resource = new Resource();
}
}
class Resource{
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.