메모리 프로파일러를 사용하여 자바 힙 및 메모리 할당 보기

메모리 프로파일러는 버벅거림, 멈춤, 심지어 앱 비정상 종료로 이어질 수 있는 메모리 누출 및 메모리 변동을 식별하는 데 도움이 되는 Android 프로파일러의 구성요소입니다. 메모리 프로파일러는 앱의 메모리 사용 현황을 실시간 그래프로 보여주며, 메모리 프로파일러를 사용하여 힙 덤프를 캡처하고 가비지 컬렉션을 강제 실행하고 메모리 할당을 추적할 수 있습니다.

메모리 프로파일러를 열려면 다음 단계를 따르세요.

  1. View > Tool Windows > Profiler를 클릭합니다(툴바에서 Profile 을 클릭해도 됩니다).
  2. Android 프로파일러 툴바에서 프로파일링할 기기 및 앱 프로세스를 선택합니다. USB를 통해 기기를 연결했는데 목록에 표시되지 않으면 USB 디버깅을 사용 설정했는지 확인하세요.
  3. MEMORY 타임라인의 아무 곳이나 클릭하여 메모리 프로파일러를 엽니다.

또는 명령줄에서 dumpsys를 사용하여 앱 메모리를 검사할 수도 있고 logcat에서 GC 이벤트를 확인할 수도 있습니다.

앱 메모리를 프로파일링해야 하는 이유

Android에서는 관리되는 메모리 환경을 제공합니다. 즉, 앱에서 일부 개체를 더 이상 사용하지 않는다고 판단되면 가비지 컬렉터가 사용되지 않는 메모리를 힙에 돌려보냅니다. Android에서 사용되지 않는 메모리를 찾는 방법은 끊임없이 개선되고 있지만, 모든 Android 버전의 특정 시점에서 시스템이 코드를 일시중지해야 합니다. 대부분의 경우 일시중지를 감지할 수 없습니다. 하지만, 시스템에서 메모리를 수집할 수 있는 것보다 빠르게 앱에서 메모리를 할당하는 경우 컬렉터가 할당하기에 충분한 메모리를 확보하는 동안 앱이 지연될 수 있습니다. 이로 인해 앱이 프레임을 건너뛰고 눈에 띄게 느려질 수 있습니다.

앱이 느려지지 않더라도 메모리 누출이 발생할 경우 앱이 백그라운드에 있는 동안에도 해당 메모리를 유지할 수 있습니다. 이 동작으로 인해 불필요한 가비지 컬렉션 이벤트가 강제로 실행되어 시스템의 나머지 메모리 성능이 저하될 수 있습니다. 결국 시스템에서 메모리를 확보하기 위해 앱 프로세스를 강제 종료해야 합니다. 그런 다음 사용자가 앱으로 돌아올 때 앱을 완전히 다시 시작해야 합니다.

이 문제를 예방하려면 메모리 프로파일러를 사용하여 다음 작업을 처리해야 합니다.

  • 타임라인에 성능 문제를 일으킬 수 있는 바람직하지 않은 메모리 할당 패턴이 있는지 찾아봅니다.
  • 자바 힙을 덤프하여 특정 시점에서 어느 개체가 메모리를 모두 사용하는지 확인합니다. 장기간 여러 번 힙을 덤프하면 메모리 누출을 식별하는 데 도움이 될 수 있습니다.
  • 정상적인 사용자 상호작용과 극단적인 사용자 상호작용 동안 메모리 할당을 기록하여 코드에서 단기간에 너무 많은 개체를 할당하거나 누출되는 개체를 할당하는 부분을 정확히 파악합니다.

앱의 메모리 사용량을 줄일 수 있는 프로그래밍 방법에 대한 정보는 앱의 메모리 관리를 읽어보세요.

메모리 프로파일러 개요

메모리 프로파일러를 처음 열면 앱의 메모리 사용 현황을 보여주는 상세 타임라인 및 가비지 컬렉션을 강제 실행하고, 힙 덤프를 캡처하고, 메모리 할당을 기록할 수 있는 액세스 도구가 표시됩니다.

그림 1. 메모리 프로파일러

그림 1에 표시된 것처럼 메모리 프로파일러의 기본 뷰에는 다음 항목이 포함됩니다.

  1. 가비지 컬렉션 이벤트를 강제 실행하기 위한 버튼.
  2. 힙 덤프를 캡처하기 위한 버튼.

    참고: 메모리 할당을 기록하기 위한 버튼은 Android 7.1(API 레벨 25) 이하를 실행하는 기기에 연결된 경우에만 힙 덤프 버튼의 오른쪽에 표시됩니다.

  3. 프로파일러에서 메모리 할당을 캡처하는 빈도를 지정하기 위한 드롭다운 메뉴. 적절한 옵션을 선택하면 프로파일링하는 동안 앱 성능을 개선하는 데 도움이 될 수도 있습니다.
  4. 타임라인을 확대/축소하기 위한 버튼.
  5. 라이브 메모리 데이터의 앞으로 건너뛰기 위한 버튼.
  6. 활동 상태, 사용자 입력 이벤트, 화면 회전 이벤트를 보여주는 이벤트 타임라인.
  7. 메모리 사용 타임라인. 다음 항목이 포함됩니다.
    • 메모리 카테고리별 메모리 사용량의 누적 그래프. 메모리 사용량은 왼쪽의 y축과 상단의 색상 키로 표시됩니다.
    • 할당된 개체의 수를 나타내는 파선. 개체 수는 오른쪽의 y축에 표시됩니다.
    • 각 가비지 컬렉션 이벤트의 아이콘.

하지만 Android 7.1 이하를 실행하는 기기를 사용하는 경우 기본적으로 모든 프로파일링 데이터가 표시되지는 않습니다. 'Advanced profiling is unavailable for the selected process'라는 메시지가 표시되는 경우 다음 항목을 표시하려면 고급 프로파일링을 사용 설정해야 합니다.

  • 이벤트 타임라인
  • 할당된 개체의 수
  • 가비지 컬렉션 이벤트

Android 8.0 이상에서는 디버그 가능한 앱에 대해 고급 프로파일링이 항상 사용 설정됩니다.

메모리 계산 방법

메모리 프로파일러 상단에는 Android 시스템에 따라 앱에서 커밋한 모든 비공개 메모리 페이지를 기반으로 한 숫자가 표시됩니다(그림 2). 시스템이나 다른 앱과 공유되는 페이지는 포함되지 않습니다.

그림 2. 메모리 프로파일러 상단의 메모리 카운트 범례

메모리 카운트의 카테고리는 다음과 같습니다.

  • Java: 자바 또는 Kotlin 코드에서 할당된 개체의 메모리.
  • Native: C 또는 C++ 코드에서 할당된 개체의 메모리.

    앱에서 C++를 사용하지 않더라도, Android 프레임워크에서 이미지 애셋 및 기타 그래픽을 처리하는 경우와 같이 개발자 대신 다양한 작업을 처리하기 위해 네이티브 메모리를 사용하므로 코드가 자바 또는 Kotlin으로 작성된 경우에도 일부 사용된 네이티브 메모리가 여기에 표시될 수 있습니다.

  • Graphics: GL 표면, GL 텍스처 등 픽셀을 화면에 표시하기 위해 그래픽 버퍼 대기열에 사용되는 메모리. (참고: 이 메모리는 전용 GPU 메모리가 아니라 CPU와 공유됩니다.)

  • Stack: 앱의 네이티브 및 자바 스택에서 사용하는 메모리. 일반적으로 앱에서 실행 중인 스레드 수와 관련이 있습니다.

  • Code: 앱에서 dex 바이트코드, 최적화되거나 컴파일된 dex 코드, .so 라이브러리, 글꼴 등 코드 및 리소스에 사용하는 메모리.

  • Others: 앱에서 사용하는 메모리 중 시스템에서 분류하는 방법을 알지 못하는 메모리.

  • Allocated: 앱에서 할당한 자바/Kotlin 개체의 수. C 또는 C++에서 할당된 개체는 포함되지 않습니다.

    Android 7.1 이하를 실행하는 기기에 연결된 경우 메모리 프로파일러가 실행 중인 앱에 연결된 때만 할당된 메모리 카운트가 계산됩니다. 따라서 프로파일링을 시작하기 전에 할당된 개체는 고려되지 않습니다. 하지만 Android 8.0 이상의 경우 모든 할당을 추적하는 온디바이스 프로파일링 도구가 포함되므로, 이 숫자는 항상 Android 8.0 이상의 앱에서 실행 중인 자바 개체의 총수를 나타냅니다.

새 메모리 프로파일러는 이전 Android 모니터 도구의 메모리 카운트와는 메모리를 다르게 기록하므로 메모리 사용량이 더 많은 것으로 보일 수도 있습니다. 메모리 프로파일러는 추가 카테고리를 모니터링하므로 총 사용량이 증가하지만, 자바 힙 메모리만 중요한 경우에는 'Java' 숫자가 이전 도구의 값과 비슷해야 합니다. Java 숫자는 아마도 Android 모니터에 표시된 숫자와 정확히 일치하지 않지만, 새로운 숫자는 Zygote에서 분기된 이후 앱의 자바 힙에 할당된 모든 물리적 메모리 페이지 수를 나타냅니다. 따라서 이 숫자는 앱에서 실제로 사용 중인 물리적 메모리의 양을 정확하게 나타냅니다.

메모리 할당 보기

메모리 할당에는 메모리의 각 자바 개체와 JNI 참조가 할당된 방식이 표시됩니다. 구체적으로 개체 할당에 대한 다음과 같은 정보가 메모리 프로파일러에 표시될 수 있습니다.

  • 할당된 개체의 유형 및 할당된 개체가 사용하는 공간의 크기.
  • 각 할당의 스택 추적(할당이 들어 있는 스레드 포함).
  • 개체가 할당 취소된 시점(Android 8.0 이상을 실행하는 기기를 사용하는 경우에만 해당).

Android 8.0 이상을 실행하는 기기에서는 언제든지 다음과 같은 방법으로 개체 할당을 확인할 수 있습니다. 타임라인을 드래그하여 할당을 확인할 영역을 선택합니다(동영상 1 참조). Android 8.0 이상에는 앱의 할당을 계속 추적하는 기기 내 프로파일링 도구가 포함되므로 기록 세션을 시작할 필요가 없습니다.

동영상 1. Android 8.0 이상을 사용하는 경우 기존 타임라인 영역을 선택하여 개체 할당 확인

Android 7.1 이하를 실행하는 기기의 경우 메모리 프로파일러 툴바의 Record memory allocations 를 클릭하세요. 기록하는 동안 메모리 프로파일러는 앱에서 발생하는 모든 할당을 추적합니다. 완료되면 Stop recording (동일한 버튼, 동영상 2 참조)을 클릭하여 할당을 확인합니다.

동영상 2. Android 7.1 이하를 사용하는 경우 메모리 할당을 명시적으로 기록해야 함

타임라인의 한 영역을 선택한 후(또는 Android 7.1 이하를 실행하는 기기를 사용하여 기록 세션을 완료한 경우) 할당된 개체의 목록이 클래스 이름별로 분류되고 힙 개수별로 정렬되어 타임라인 아래 표시됩니다.

할당 기록을 검사하려면 다음 단계를 따르세요.

  1. 목록을 둘러보고 힙 개수가 비정상적으로 크고 누출될 가능성이 있는 개체를 찾습니다. 알려진 클래스를 찾으려면 Class Name 열 헤더를 클릭하여 알파벳순으로 정렬하세요. 그런 다음, 클래스 이름을 클릭합니다. 오른쪽에 Instance View 창이 표시되고, 그림 3과 같이 해당 클래스의 각 인스턴스가 표시됩니다.
    • 또는 Filter 를 클릭하거나 Control+F(Mac의 경우 Command+F)를 누르고 검색 필드에 클래스 또는 패키지 이름을 입력하여 신속하게 개체를 찾을 수 있습니다. 드롭다운 메뉴에서 Arrange by callstack을 선택한 경우 메서드 이름으로 검색할 수도 있습니다. 정규 표현식을 사용하려면 Regex 옆의 체크박스를 선택하세요. 대소문자를 구분하는 검색어의 경우 Match case 옆의 체크박스를 선택하세요.
  2. Instance View 창에서 인스턴스를 클릭합니다. 아래에 Call Stack 탭이 표시되고 인스턴스가 할당된 위치 및 인스턴스가 들어 있는 스레드가 표시됩니다.
  3. Call Stack 탭에서 아무 줄이나 마우스 오른쪽 버튼으로 클릭하고 Jump to Source를 선택하여 편집기에서 코드를 엽니다.

그림 3. 할당된 각 개체에 대한 세부정보가 오른쪽의 Instance View에 표시됨

할당된 개체 목록 위의 두 메뉴를 사용하여 어떤 힙을 검사할지와 데이터를 구성하는 방법을 선택할 수 있습니다.

왼쪽 메뉴에서 검사할 힙을 선택합니다.

  • default heap: 시스템에서 힙을 지정하지 않은 경우.
  • image heap: 부팅하는 동안 미리 로드된 클래스가 포함된 시스템 부팅 이미지. 여기서는 할당이 결코 이동하거나 사라지지 않습니다.
  • zygote heap: Android 시스템에서 앱 프로세스가 분기되는 COW(기록 중 복사) 힙.
  • app heap: 앱에서 메모리를 할당하는 기본 힙.
  • JNI heap: JNI(Java Native Interface) 참조가 할당되고 해제되는 위치를 보여주는 힙.

오른쪽 메뉴에서 할당을 정렬할 방법을 선택합니다.

  • Arrange by class: 클래스 이름을 기반으로 모든 할당을 분류합니다. 기본값입니다.
  • Arrange by package: 패키지 이름을 기반으로 모든 할당을 분류합니다.
  • Arrange by callstack: 모든 할당을 호출 스택으로 분류합니다.

프로파일링하는 동안 앱 성능 개선

프로파일링하는 동안 앱 성능을 개선하기 위해 메모리 프로파일러는 기본적으로 메모리 할당 샘플을 주기적으로 추출합니다. API 레벨 26 이상을 실행하는 기기에서 테스트하는 경우 Allocation Tracking 드롭다운을 사용하여 이 동작을 변경할 수 있습니다. 다음과 같은 옵션을 사용할 수 있습니다.

  • Full: 메모리의 모든 개체 할당을 캡처합니다. Android 스튜디오 3.2 이전 버전의 경우 기본 동작입니다. 앱에서 많은 개체를 할당하는 경우 프로파일링하는 동안 앱이 눈에 띄게 느려질 수 있습니다.
  • Sampled: 일정한 간격으로 메모리에서 개체 할당 샘플을 추출합니다. 기본 옵션으로, 프로파일링하는 동안 앱 성능에 미치는 영향이 적습니다. 단기간에 많은 개체를 할당하는 앱은 여전히 눈에 띄게 느려질 수 있습니다.
  • Off: 앱의 메모리 할당 추적을 중지합니다.

글로벌 JNI 참조 보기

JNI(Java Native Interface)는 자바 코드 및 네이티브 코드가 서로를 호출할 수 있는 프레임워크입니다.

JNI 참조는 네이티브 코드에 의해 수동으로 관리되므로 네이티브 코드에서 사용하는 자바 개체가 너무 오랫동안 연결된 상태로 유지될 수 있습니다. JNI 참조가 먼저 명시적으로 삭제되지 않고 취소되면 자바 힙의 일부 개체에 도달하지 못할 수도 있습니다. 또한 글로벌 JNI 참조 한도를 소진할 수도 있습니다.

이러한 문제를 해결하려면 메모리 프로파일러의 JNI heap 뷰를 사용하여 모든 글로벌 JNI 참조를 둘러보고 자바 유형 및 네이티브 호출 스택을 기준으로 필터링하세요. 이 정보를 사용하여 글로벌 JNI 참조가 생성되고 삭제되는 시기와 위치를 알 수 있습니다.

앱이 실행되는 동안 검사하려는 타임라인 부분을 선택하고, 클래스 목록 위의 드롭다운 메뉴에서 JNI heap을 선택합니다. 그런 다음 그림 4에 표시된 것처럼 평소와 같이 힙에 있는 개체를 검사하고, Allocation Call Stack 탭에서 개체를 더블클릭하여 코드에서 JNI 참조가 할당되고 해제된 위치를 확인할 수 있습니다.

그림 4. 글로벌 JNI 참조 보기

앱의 JNI 코드에 대한 메모리 할당을 검사하려면 Android 8.0 이상을 실행하는 기기에 앱을 배포해야 합니다.

JNI에 관한 자세한 내용은 JNI 팁을 참조하세요.

힙 덤프 캡처

힙 덤프는 힙 덤프를 캡처할 때 앱에서 메모리를 사용 중인 개체를 보여줍니다. 특히 장기적인 사용자 세션 후, 더 이상 메모리에 없어야 한다고 생각되는데 아직 메모리에 있는 개체를 보여주므로 메모리 누출을 식별하는 데 도움이 됩니다.

힙 덤프를 캡처한 후 다음 정보를 확인할 수 있습니다.

  • 앱에서 할당한 개체의 유형 및 각 유형의 개체 수
  • 각 개체가 사용 중인 메모리의 양
  • 코드에서 각 개체의 참조가 유지되는 위치
  • 개체가 할당된 호출 스택 (현재는 할당을 기록하는 동안 힙 덤프를 캡처할 때 Android 7.1 이하에서만 힙 덤프와 함께 호출 스택을 사용할 수 있습니다.)

힙 덤프를 캡처하려면 메모리 프로파일러 툴바에서 Dump Java heap 을 클릭하세요. 힙을 덤프하는 동안 자바 메모리의 양이 일시적으로 증가할 수도 있습니다. 자바 메모리의 양이 증가하는 것은 힙 덤프가 앱과 동일한 프로세스에서 발생하고 데이터를 수집하기 위해 메모리가 필요하므로 정상적인 현상입니다.

그림 5와 같이 힙 덤프가 메모리 타임라인 아래에 표시되며 힙의 모든 클래스 유형을 보여줍니다.

그림 5. 힙 덤프 보기

덤프가 언제 생성되는지 더 정확히 알아야 하는 경우 dumpHprofData()를 호출하여 앱 코드의 중요한 지점에서 힙 덤프를 생성할 수 있습니다.

클래스의 목록에서 다음 정보를 확인할 수 있습니다.

  • Allocations: 힙의 할당 수.
  • Native Size: 이 개체 유형에서 사용하는 총 네이티브 메모리의 양(바이트). 이 열은 Android 7.0 이상의 경우에만 표시됩니다.

    Android에서 Bitmap 등 일부 프레임워크 클래스에는 네이티브 메모리를 사용하므로 자바에서 할당된 일부 개체의 경우 여기에 메모리가 표시됩니다.

  • Shallow Size: 이 개체 유형에서 사용하는 총 자바 메모리의 양(바이트).

  • Retained Size: 이 클래스의 모든 인스턴스로 인해 유지되는 총 메모리 크기(바이트).

할당된 개체 목록 위의 두 메뉴를 사용하여 어떤 힙 덤프를 검사할지와 데이터를 구성하는 방법을 선택할 수 있습니다.

왼쪽 메뉴에서 검사할 힙을 선택합니다.

  • default heap: 시스템에서 힙을 지정하지 않은 경우.
  • app heap: 앱에서 메모리를 할당하는 기본 힙.
  • image heap: 부팅하는 동안 미리 로드된 클래스가 포함된 시스템 부팅 이미지. 여기서는 할당이 결코 이동하거나 사라지지 않습니다.
  • zygote heap: Android 시스템에서 앱 프로세스가 분기되는 COW(기록 중 복사) 힙.

오른쪽 메뉴에서 할당을 정렬할 방법을 선택합니다.

  • Arrange by class: 클래스 이름을 기반으로 모든 할당을 분류합니다. 기본값입니다.
  • Arrange by package: 패키지 이름을 기반으로 모든 할당을 분류합니다.
  • Arrange by callstack: 모든 할당을 호출 스택으로 분류합니다. 이 옵션은 할당을 기록하는 동안 힙 덤프를 캡처하는 경우에만 작동합니다. 그렇지만 힙에 기록을 시작하기 전에 할당된 개체가 있을 수 있으므로 이러한 할당이 클래스 이름별로 나열되어 먼저 표시됩니다.

목록은 기본적으로 Retained Size 열을 기준으로 정렬됩니다. 다른 열의 값을 기준으로 정렬하려면 열의 제목을 클릭하세요.

클래스 이름을 클릭하면 오른쪽에 Instance View 창이 열립니다(그림 6 참조). 각 인스턴스에는 다음과 같은 항목이 나열됩니다.

  • Depth: 임의의 GC 루트에서 선택된 인스턴스까지 가장 짧은 홉 수.
  • Native Size: 네이티브 메모리에서 이 인스턴스의 크기. 이 열은 Android 7.0 이상의 경우에만 표시됩니다.
  • Shallow Size: 자바 메모리에서 이 인스턴스의 크기.
  • Retained Size: 도미네이터 트리당 이 인스턴스가 지배하는 메모리의 크기.

그림 6. 힙 덤프를 캡처하기 위해 필요한 기간이 타임라인에 표시됨

힙을 검사하려면 다음 단계를 따르세요.

  1. 목록을 둘러보고 힙 개수가 비정상적으로 크고 누출될 가능성이 있는 개체를 찾습니다. 알려진 클래스를 찾으려면 Class Name 열 헤더를 클릭하여 알파벳순으로 정렬하세요. 그런 다음, 클래스 이름을 클릭합니다. 오른쪽에 Instance View 창이 표시되고, 그림 6과 같이 해당 클래스의 각 인스턴스가 표시됩니다.
    • 또는 Filter 를 클릭하거나 Control+F(Mac의 경우 Command+F)를 누르고 검색 필드에 클래스 또는 패키지 이름을 입력하여 신속하게 개체를 찾을 수 있습니다. 드롭다운 메뉴에서 Arrange by callstack을 선택한 경우 메서드 이름으로 검색할 수도 있습니다. 정규 표현식을 사용하려면 Regex 옆의 체크박스를 선택하세요. 대소문자를 구분하는 검색어의 경우 Match case 옆의 체크박스를 선택하세요.
  2. Instance View 창에서 인스턴스를 클릭합니다. 아래에 References 탭이 표시되고 해당 개체에 대한 모든 참조가 표시됩니다.

    또는 인스턴스 이름 옆의 화살표를 클릭하여 모든 필드를 표시한 다음, 필드 이름을 클릭하여 필드의 모든 참조를 확인합니다. 필드의 인스턴스 세부정보를 보려면 필드를 마우스 오른쪽 버튼으로 클릭하고 Go to Instance를 선택합니다.

  3. References 탭에서 메모리를 누출할 가능성이 있는 참조가 식별된 경우 마우스 오른쪽 버튼으로 클릭하고 Go to Instance를 선택합니다. 이렇게 하면 힙 덤프에서 해당 인스턴스가 선택되고 자체 인스턴스 데이터가 표시됩니다.

힙 덤프에서 다음과 같은 원인으로 인해 발생한 메모리 누출이 있는지 확인하세요.

  • Activity, Context, View, Drawable 및 기타 Activity 또는 Context 컨테이너에 대한 참조를 보유할 수도 있는 개체에 대한 장기적인 참조.
  • Runnable과 같이 Activity 인스턴스를 보유할 수 있는 비정적 내부 클래스.
  • 필요 이상으로 오랫동안 개체를 보유하는 캐시.

힙 덤프를 HPROF 파일로 저장

힙 덤프를 캡처한 후에는 프로파일링을 실행하는 동안에만 메모리 프로파일러에 데이터가 표시됩니다. 프로파일링 세션을 종료하면 힙 덤프를 잃게 됩니다. 따라서 나중에 검토하기 위해 힙 덤프를 저장하려면 HPROF 파일로 내보내세요. Android 스튜디오 3.1 이하에서는 타임라인 아래 툴바 왼쪽에 Export capture to file 버튼이 있고, Android 스튜디오 3.2 이상에서는 Sessions 창의 각 Heap Dump 항목 오른쪽에 Export Heap Dump 버튼이 있습니다. Export As 대화상자가 표시되면 .hprof 파일 이름 확장자를 사용하여 파일을 저장하세요.

jhat과 같은 다른 HPROF 분석기를 사용하려면 HPROF 파일을 Android 형식에서 자바 SE HPROF 형식으로 변환해야 합니다. android_sdk/platform-tools/ 디렉터리에 제공된 hprof-conv 도구를 사용하여 변환할 수 있습니다. 두 개의 인수, 즉 원본 HPROF 파일과 변환된 HPROF 파일을 기록할 위치를 사용하여 hprof-conv 명령어를 실행하세요. 예:

hprof-conv heap-original.hprof heap-converted.hprof
    

힙 덤프 파일 가져오기

HPROF(.hprof) 파일을 가져오려면 Sessions 창에서 Start a new profiling session 을 클릭하고 Load from file을 선택한 후 파일 브라우저에서 파일을 선택하세요.

HPROF 파일을 파일 브라우저에서 편집기 창으로 드래그하여 가져올 수도 있습니다.

메모리 프로파일링 기법

메모리 프로파일러를 사용하는 동안 앱 코드에 스트레스를 주어 강제로 메모리 누출을 유발해야 합니다. 앱에서 메모리 누출을 유발하는 한 가지 방법은 힙을 검사하기 전에 잠시 동안 앱이 실행되도록 하는 것입니다. 메모리가 힙의 할당 상한까지 서서히 누출될 수 있습니다. 하지만 누출이 적을수록 더 오랫동안 앱을 실행해야 누출을 확인할 수 있습니다.

다음 중 한 가지 방법으로 메모리 누출을 트리거할 수도 있습니다.

  • 기기가 다양한 활동 상태에 있는 동안 기기를 세로 모드에서 가로 모드로 회전했다가 다시 되돌리기를 여러 번 반복합니다. 기기를 회전하면 앱에서 Activity, Context 또는 View 개체를 누출하는 경우가 있습니다. 이는 시스템에서 Activity를 다시 만들고, 앱에서 이러한 개체 중 하나에 대한 참조를 다른 곳에 유지하는 경우 시스템에서 해당 개체를 가비지 컬렉션할 수 없기 때문입니다.
  • 다양한 활동 상태에 있는 동안 개발자의 앱과 다른 앱 간을 전환합니다(홈 화면으로 이동한 다음 개발자의 앱으로 돌아옵니다).

팁: monkeyrunner 테스트 프레임워크를 사용하여 위의 단계를 수행할 수도 있습니다.