Android 메모리 누 출 가능 한 몇 가지 요약

자바 는 쓰레기 회수 언어의 하나 로 개발 자가 메모리 분 배 를 특별히 관리 하지 않 아 도 되 고 응용 프로그램 이 국부 고장(segmentation fault)으로 인해 붕괴 되 는 것 을 낮 추 는 동시에 방출 되 지 않 은 메모리 가 스 택(hep)을 폭발 시 킬 가능성 을 방지 하기 때문에 쓴 코드 가 더욱 안전 하 다 는 것 이 장점 이다.
불 행 히 도 자바 에는 메모리 누 출 을 초래 하기 쉬 운 논리 적 가능성(logical leak)이 많다.조심 하지 않 으 면,당신 의 안 드 로 이 드 응용 프로그램 은 방출 되 지 않 은 메모 리 를 낭비 하기 쉬 우 며,결국 메모리 가 빛 을 사용 하 는 오류 가 발생 합 니 다(out-of-memory,OOM).
일반 메모리 누 출(traditional memory leak)의 이 유 는 이 대상 의 모든 인용 이 풀 렸 을 때 대상 이 풀 리 지 않 았 기 때 문 입 니 다.(번역자 주:Cursor 가 닫 는 것 을 잊 어 버 리 는 등)
논리 메모리 누설(logical memory leak)의 이 유 는 응용 프로그램 이 더 이상 이 대상 을 필요 로 하지 않 을 때 이 대상 의 모든 인용 을 방출 하지 않 을 때 입 니 다.
대상 의 강 한 인용 을 가지 고 있다 면 쓰레기 수 거 기 는 메모리 에서 이 대상 을 회수 할 수 없습니다.
안 드 로 이 드 개발 에서 가장 쉽게 발생 하 는 메모리 유출 문 제 는 Context 다.예 를 들 어 Activity 의 Context 는 View Hierarchies 와 다른 자원 등 대량의 메모리 인용 을 포함한다.Context 가 누설 되면 그 대상 이 가리 키 는 모든 대상 을 누설 하 는 것 을 의미한다.안 드 로 이 드 기기 의 메모리 가 제한 되 어 있어 서 너무 많은 메모리 누 출 은 OOM 을 초래 하기 쉽다.
논리 적 메모리 누 출 을 감지 하려 면 주관적 인 판단 이 필요 하 며,특히 대상 의 생명 주기 가 뚜렷 하지 않다.다행히 액 티 비 티 는 명확 한 라 이 프 사이클 을 갖 고 있어 유출 원인 을 쉽게 발견 할 수 있다.Activity.onDestroy()는 Activity 생명의 끝 으로 여 겨 집 니 다.프로그램 을 보면 소각 되 거나 Android 시스템 이 이 메모리 들 을 회수 해 야 합 니 다.
이 방법 이 실행 되면 스 택 에 이 Activity 를 가 진 강 한 인용 이 존재 합 니 다.쓰레기 수 거 기 는 회수 한 메모리 로 표시 할 수 없습니다.우 리 는 원래 그것 을 회수 하 는 것 이 목적 입 니 다!
결 과 는 Activity 가 수명 주기 밖 에 살아 있다 는 것 이다.
Activity 는 헤비급 대상 이 므 로 안 드 로 이 드 시스템 이 처리 하도록 해 야 합 니 다.그러나 논리 적 메모리 누 출 은 항상 부주의 로 발생 한다.번역자 주:Activity 를 사용 하여 20M 메모리 누 출 을 시도 한 적 이 있 습 니 다.Android 에서 잠재 적 인 메모리 누 출 을 초래 하 는 함정 은 두 가지 가 있 습 니 다.
1.전역 프로 세 스(process-global)의 static 변수.애플 리 케 이 션 을 무시 한 상태 로 액 티 비 티 의 강 한 인용 을 가 진 몬스터.
2.Activity 라 이 프 사이클 이외 의 스 레 드.Activity 에 대한 강 한 인용 을 비우 지 않 았 습 니 다.
당신 이 아래 의 상황 을 만 났 는 지 검사 해 보 세 요.
Static Activities
클래스 에서 정적 Activity 변 수 를 정의 하고 현재 실행 중인 Activity 인 스 턴 스 를 이 정적 변수 에 할당 합 니 다.
이 정적 변수 가 Activity 수명 주기 가 끝 난 후에 비 워 지지 않 으 면 메모리 가 누 출 됩 니 다.static 변 수 는 이 애플 리 케 이 션 의 라 이 프 사이클 을 관통 하기 때문에 누 출 된 Activity 는 애플 리 케 이 션 프로 세 스에 계속 존재 하 며 쓰레기 수 거 기 를 통 해 회수 되 지 않 습 니 다.

  static Activity activity;

  void setStaticActivity() {
   activity = this;
  }

  View saButton = findViewById(R.id.sa_button);
  saButton.setOnClickListener(new View.OnClickListener() {
   @Override public void onClick(View v) {
    setStaticActivity();
    nextActivity();
   }
  });


Memory Leak 1 C Static Activity
Static Views
유사 한 상황 은 단일 모드 에서 발생 합 니 다.Activity 가 자주 사용 된다 면 메모리 에 인 스 턴 스 를 저장 하 는 것 이 실 용적 입 니 다.앞서 밝 힌 바 와 같이 액 티 비 티 의 생명 주 기 를 강제로 연장 하 는 것 은 상당히 위험 하고 불필요 하 며 어떻게 든 그렇게 할 수 없다.
특수 상황:하나의 View 가 초기 화 되 어 많은 자원 을 소모 하고 하나의 Activity 수명 주기 내 에 변 하지 않 으 면 static 로 바 꾸 어 보기 트 리 에 불 러 올 수 있 습 니 다(View Hierachy).이렇게 하면 Activity 가 소 멸 될 때 자원 을 방출 해 야 합 니 다.(번역자 주:예제 코드 에 메모리 가 방출 되 지 않 았 습 니 다.이 static view 를 null 로 설정 하면 됩 니 다.그러나 이 static view 를 사용 하 는 방법 은 권장 하지 않 습 니 다)

  static view;

  void setStaticView() {
   view = findViewById(R.id.sv_button);
  }

  View svButton = findViewById(R.id.sv_button);
  svButton.setOnClickListener(new View.OnClickListener() {
   @Override public void onClick(View v) {
    setStaticView();
    nextActivity();
   }
  });



Memory Leak 2 C Static View
Inner Classes
계속해서 Activity 에 내부 클래스 가 있다 고 가정 하면 가 독성 과 봉인 성 을 높 일 수 있다.예 를 들 어 우리 가 내부 클래스 를 만 들 고 정적 변수의 인용 을 가지 고 있 습 니 다.축하합니다.메모리 누 출 은 멀 지 않 습 니 다.

 private static Object inner;

    void createInnerClass() {
    class InnerClass {
    }
    inner = new InnerClass();
  }

  View icButton = findViewById(R.id.ic_button);
  icButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
      createInnerClass();
      nextActivity();
    }
  });


Memory Leak 3 C Inner Class
내부 클래스 의 장점 중 하 나 는 외부 클래스 를 방문 할 수 있다 는 것 이다.불행 하 게 도 메모리 누 출 을 초래 하 는 원인 은 내부 클래스 가 외부 클래스 의 인 스 턴 스 를 가지 고 있 는 강 한 인용 이다.
Anonymous Classes
비슷 하 게 익명 류 도 외부 류 의 인용 을 유지 했다.그래서 메모리 누 출 이 쉽게 발생 합 니 다.Activity 에서 익명 의 AsyncTsk 를 정의 하면
。비동기 작업 이 배경 에서 시간 소모 작업 을 수행 하 는 동안 Activity 는 불행 하 게 도 소각 되 었 습 니 다.

 void startAsyncTask() {
    new AsyncTask<Void, Void, Void>() {
      @Override protected Void doInBackground(Void... params) {
        while(true);
      }
    }.execute();
  }

  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  View aicButton = findViewById(R.id.at_button);
  aicButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
      startAsyncTask();
      nextActivity();
    }
  });


Memory Leak 4 C AsyncTask
Handler
마찬가지 로 익명 의 Runnable 을 정의 하고 익명 의 Handler 로 실행 합 니 다.Runnable 내부 클래스 는 외부 클래스 의 암시 적 인용 을 가지 고 있 으 며 Handler 메시지 큐 에 전 달 된 Message Queue 에 서 는 Message 메시지 가 처리 되 지 않 을 때 까지 Activity 인 스 턴 스 가 삭제 되 지 않 아 메모리 가 누 출 됩 니 다.

 void createHandler() {
    new Handler() {
      @Override public void handleMessage(Message message) {
        super.handleMessage(message);
      }
    }.postDelayed(new Runnable() {
      @Override public void run() {
        while(true);
      }
    }, Long.MAX_VALUE >> 1);
  }

  View hButton = findViewById(R.id.h_button);
  hButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
      createHandler();
      nextActivity();
    }
  });


Memory Leak 5 C Handler
Threads
우 리 는 다시 Thread 와 Timer Task 를 통 해 메모리 누 출 을 보 여 줍 니 다.

  void spawnThread() {
    new Thread() {
      @Override public void run() {
        while(true);
      }
    }.start();
  }

  View tButton = findViewById(R.id.t_button);
  tButton.setOnClickListener(new View.OnClickListener() {
   @Override public void onClick(View v) {
     spawnThread();
     nextActivity();
   }
  });


Memory Leak 6 C Thread
TimerTask
익명 클래스 의 인 스 턴 스 라면 작업 스 레 드 든 아니 든 Activity 의 인용 을 가지 고 있어 메모리 가 누 출 됩 니 다.

 void scheduleTimer() {
    new Timer().schedule(new TimerTask() {
      @Override
      public void run() {
        while(true);
      }
    }, Long.MAX_VALUE >> 1);
  }

  View ttButton = findViewById(R.id.tt_button);
  ttButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
      scheduleTimer();
      nextActivity();
    }
  });


Memory Leak 7 C TimerTask
Sensor Manager
마지막 으로 Context.getSystemService(int name)를 통 해 시스템 서 비 스 를 받 을 수 있 습 니 다.이러한 서 비 스 는 각자 의 프로 세 스에 서 백 엔 드 작업 을 처리 하고 하드웨어 상호작용 을 처리 하 는 데 도움 을 준다.이 서 비 스 를 사용 해 야 할 경우 감청 기 를 등록 할 수 있 고,이 는 서비스 가 Context 인용 을 보유 하 게 되 며,Activity 가 폐 기 될 때 이 감청 기 를 말소 하지 않 으 면 메모리 유출 로 이 어 질 수 있다.

  void registerListener() {
        SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
        sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
    }

    View smButton = findViewById(R.id.sm_button);
    smButton.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
        registerListener();
        nextActivity();
      }
    });


Memory Leak 8 C Sensor Manager
총결산
그렇게 많은 메모리 누 출 을 초래 할 수 있 는 예 를 보면 휴대 전화의 메모 리 를 다 먹 어 버 리 기 쉬 워 쓰레기 회수 처리 가 더욱 빈번 해 지고 심지어 최 악의 경우 OOM 을 초래 할 수 있다.쓰레기 회수 작업 은 비 싼 비용 으로 육안 으로 볼 수 있 는 카드 를 만 들 수 있다.따라서 실례 화 할 때 소지 하고 있 는 인용 체인 에 주의 하고 메모리 누 출 검 사 를 자주 한다.
이상 은 안 드 로 이 드 메모리 에 누 출 된 자 료 를 정리 하고 관련 자 료 를 계속 보충 하 는 것 입 니 다.본 사이트 에 대한 지원 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기