힙 덤프 캡처

힙 덤프를 캡처하여 캡처 시점에 앱에서 메모리를 사용 중인 객체를 확인하고 메모리 누수 또는 끊김 현상, 멈춤, 심지어 앱 비정상 종료로 이어지는 메모리 할당 동작을 식별합니다. 특히 객체를 계속 표시할 수 있을 때 확장된 사용자 세션 후에 힙 덤프를 가져옴 더 이상 존재하지 않아야 하는 메모리에 있을 수 있습니다.

이 페이지에서는 Android 스튜디오에서 제공하는 도구를 설명합니다. 힙 덤프를 분석할 수 있습니다 또는 다음과 같은 방법으로 앱 메모리를 검사할 수 있습니다. 명령줄에서 dumpsys을 사용하고 Logcat의 가비지 컬렉션 (GC) 이벤트

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

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

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

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

힙 덤프 개요

힙 덤프를 캡처하려면 메모리 사용량 분석(힙 덤프) 작업을 선택합니다(프로파일러: 디버그 가능한 '앱' 실행(데이터 완료) 사용). 그러면 힙 덤프가 캡처됩니다. 힙을 덤프하는 동안 Java 메모리의 양이 증가할 수 있음 일시적으로 힙 덤프가 데이터를 수집하려면 약간의 메모리가 필요합니다. 힙 덤프를 캡처하면 다음이 표시됩니다.

클래스 목록에는 다음 정보가 표시됩니다.

  • Allocations: 힙의 할당 수.
  • Native Size: 이 객체 유형에서 사용하는 총 네이티브 메모리 양 (단위: 바이트) Android에서 Bitmap 등 일부 프레임워크 클래스에 네이티브 메모리를 사용하므로 자바에서 할당된 일부 객체의 경우 여기에 메모리가 표시됩니다.

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

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

힙 메뉴를 사용하여 특정 힙으로 필터링합니다.

  • 앱 힙(기본값): 앱에서 메모리를 할당하는 기본 힙입니다.
  • 이미지 힙: 미리 로드된 클래스가 포함된 시스템 부팅 이미지입니다. 발생할 수 있습니다 여기서는 할당이 이동하거나 사라지지 않습니다.
  • Zygote 힙: Android 시스템에서 앱 프로세스가 포크되는 COW(기록 중 복사) 힙.

정렬 드롭다운을 사용하여 할당을 정렬하는 방법을 선택합니다.

  • Arrange by class(클래스별 정렬)(기본값): 클래스 이름을 기준으로 모든 할당을 그룹화합니다.
  • Arrange by package: 패키지 이름을 기반으로 모든 할당을 분류합니다.

수업 드롭다운을 사용하여 수업 그룹으로 필터링합니다.

  • 모든 클래스(기본값): 라이브러리 및 종속 항목의 클래스를 포함한 모든 클래스를 표시합니다.
  • Activity/Fragment Leaks 표시: 메모리 누수를 일으키는 클래스를 표시합니다.
  • Show project Class: 프로젝트에서 정의한 클래스만 표시합니다.

클래스 이름을 클릭하여 인스턴스 창을 엽니다. 나열된 각 인스턴스에는 다음이 포함됩니다.

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

인스턴스를 클릭하여 필드참조를 비롯한 인스턴스 세부정보를 표시합니다. 일반적인 필드 및 참조 유형은 Java의 구조화된 유형 , 배열 , 기본 데이터 유형 입니다. 필드 또는 참조를 마우스 오른쪽 버튼으로 클릭하여 소스 코드에서 연결된 인스턴스 또는 줄로 이동합니다.

  • 필드: 이 인스턴스의 모든 필드를 표시합니다.
  • 참조: 인스턴스 탭에서 강조 표시된 객체에 대한 모든 참조를 표시합니다.

메모리 누수 찾기

메모리 누수와 관련이 있을 수 있는 클래스로 빠르게 필터링하려면 클래스 드롭다운을 열고 Show activity/fragment leaks를 선택합니다. Android 스튜디오에서는 앱의 ActivityFragment 인스턴스에서 메모리 누수가 의심되는 클래스를 표시합니다. 필터에 표시되는 데이터 유형은 다음과 같습니다.

  • 삭제되었지만 아직 참조되고 있는 Activity 인스턴스
  • Fragment 유효한 FragmentManager이지만 여전히 있습니다.

다음과 같은 상황에서는 필터에 거짓양성이 표시될 수 있습니다.

  • Fragment를 생성하였지만 아직 사용하지 않은 경우
  • Fragment가 캐시되고 있지만 FragmentTransaction의 일부가 아닌 경우

메모리 누출을 더 수동으로 찾으려면 클래스 및 인스턴스 목록을 둘러보고 Retained Size가 큰 객체를 찾습니다. 다음과 같은 원인으로 인한 메모리 누수가 있는지 살펴보세요.

  • Activity, Context, View, DrawableActivity 또는 Context 컨테이너 참조를 보유할 수 있는 기타 객체에 대한 장기 참조
  • Activity 인스턴스를 보유할 수 있는 비정적 내부 클래스(예: Runnable)
  • 필요 이상으로 오랫동안 객체를 보유하는 캐시

메모리 누수 가능성을 발견하면 필드참조 탭을 사용합니다. Instance Details(인스턴스 세부정보)를 클릭하여 원하는 인스턴스 또는 소스 코드 줄로 이동합니다.

테스트를 위한 메모리 누수 트리거

메모리 사용량을 분석하려면 앱 코드에 스트레스를 받고 강제로 메모리를 늘려야 합니다. 있습니다 앱에서 메모리 누수를 유발하는 한 가지 방법은 앱이 잠시 동안 실행되도록 두는 것입니다. 확인해야 합니다 메모리가 힙의 할당 상한까지 서서히 누수될 수 있습니다. 하지만 누수가 적을수록 앱을 더 오래 실행해야 합니다. 볼 수 있습니다.

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

  • 기기가 다양한 활동 상태에 있는 동안 기기를 세로 모드에서 가로 모드로 회전했다가 다시 되돌리기를 여러 번 반복합니다. 기기를 회전하면 앱이 Activity를 유출합니다. Context 또는 View 객체를 반환합니다. Activity, 앱이 이러한 객체 중 하나에 대한 참조를 보유하는 경우 시스템은 가비지 컬렉션을 할 수 없습니다.
  • 다양한 활동 상태에서 앱과 다른 앱 간에 전환합니다. 예를 들어 홈 화면으로 이동한 다음 앱으로 돌아갑니다.

힙 덤프 기록 내보내기 및 가져오기

프로파일러의 이전 녹음 파일 탭에서 힙 덤프 파일을 내보내고 가져올 수 있습니다. Android 스튜디오는 .hprof 파일로 녹화됩니다.

또는 jhat과 같은 다른 .hprof 파일 분석기를 사용하려면 .hprof 파일을 Android 형식에서 Java SE .hprof 파일 형식으로 변환해야 합니다. 파일 형식을 변환하려면 {android_sdk}/platform-tools/ 디렉터리에 있는 hprof-conv 도구를 사용하세요. 원본 .hprof 파일 이름과 변환된 .hprof 파일을 작성할 위치(새 .hprof 파일 이름 포함)를 인수로 사용하여 hprof-conv 명령어를 실행합니다. 예를 들면 다음과 같습니다.

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