Android 스튜디오의 Logcat 창에는 시스템 메시지(예: 가비지 컬렉션 발생)와 관심 있는 정보만 표시하기 위해 필터를 만들고, 메시지에 표시되는 정보의 양을 수정하고, 우선순위 레벨을 설정하고, 앱 코드를 통해 생성된 메시지만 표시하고, 로그를 검색할 수 있습니다. 기본적으로 Logcat은 가장 최근 실행한 앱과 관련된 로그 출력만 보여줍니다. 앱에서 예외가 발생하면 Logcat은 메시지를 표시한 다음 코드 줄 링크를 포함한 연결된 스택 트레이스를 표시합니다. Android 스튜디오 2.2부터는 Run 창에 현재 실행 중인 앱의 로그 메시지도 표시됩니다. 참고로 Logcat 출력 화면은 구성할 수 있지만, Run 창은 구성할 수 없습니다. 앱의 로그 메시지를 표시하려면 다음을 따르세요. Logcat 창은 그림 1과 같이 창의 상단에 있는 드롭다운 목록에서 선택한 대로 선택된 앱의 로그 메시지를 표시합니다. 그림 1. Logcat 창 기본적으로 Logcat은 기기에서 실행 중인 앱의 로그 메시지만 표시합니다. 이 기본값을 변경하려면 Logcat 메시지 필터링 방법을 참조하세요. Logcat 툴바는 다음과 같은 버튼을 제공합니다.
로그 메시지 작성
전체 옵션 목록은 개발 단계를 제외하고 상세 로그를 앱으로 컴파일하면 안 됩니다. 디버그 로그는 런타임에 컴파일되지만 삭제되는 반면, 오류, 경고, 정보 로그는 계속 유지됩니다. 각 로그 메서드에서 첫 번째 매개변수는 고유한 태그여야 하며 두 번째 매개변수는 메시지입니다. 시스템
로그 메시지의 태그는 메시지가 발생한 시스템 구성요소를 가리키는 짧은 문자열입니다(예: 첫 번째 매개변수에서 사용할 클래스에
참고: 태그 이름이 23자를 초과하는 경우 Logcat 출력에서 잘립니다. Logcat 메시지 형식 모든 Android 로그 메시지에는 태그 및 태그와 연관된 우선순위가 있습니다. 시스템 로그 메시지의 태그는 메시지가 발생한 시스템 구성요소(예:
우선순위는 다음 값 중 하나입니다.
로그 메시지 형식은 다음과 같습니다. date time PID-TID/package priority/tag: message 예를 들어, 다음 로그 메시지의 우선순위는 12-10 13:02:50.071 1901-4229/com.google.android.gms V/AuthZen: Handling delegate intent. PID는 프로세스 식별자(process identifier), TID는 스레드 식별자(thread identifier)를 나타내며, 스레드가 하나만 있을 때는 두 식별자가 같을 수 있습니다. 로그 레벨 설정로그 레벨을 설정하여 Logcat에 표시할 메시지 수를 제어할 수 있습니다. 모든 메시지를 표시할 수도 있고 가장 엄격한 조건을 나타내는 메시지만 표시할 수도 있습니다. 로그 레벨 설정과 관계없이 Logcat은 계속 모든 메시지를 수집합니다. 이 설정은 단순히 Logcat이 무엇을 표시할지 결정합니다. 로그 레벨 메뉴에서 다음 값 중 하나를 선택합니다.
Logcat 메시지 검색현재 Logcat에 표시된 메시지를 검색하려면 다음을 따르세요.
Logcat 메시지 필터링로그 출력을 관리 가능한 수준으로 줄이는 한 가지 방법은 필터를 사용해 로그 출력을 제한하는 것입니다. 참고: 필터는 Logcat에 현재 표시되고 있는 메시지뿐만 아니라 전체 Logcat 기록에 적용됩니다. 검사하려는 필터 출력을 볼 수 있도록 다른 표시 옵션이 알맞게 설정되어 있는지 확인하세요. 필터를 정의하고 적용하는 방법은 다음과 같습니다.
원하는 로그 메시지가 표시되지 않으면 No filters를 선택하고 해당 로그 메시지를 검색해 보세요. 가비지 컬렉션 메시지 읽기가비지 컬렉션 이벤트가 발생하면 Logcat에 출력됩니다. 앱 메모리에 관한 자세한 정보는 메모리 프로파일러를 사용하세요. Dalvik 로그 메시지Dalvik(ART 아님)에서는 모든 GC가 Logcat에 다음 정보를 출력합니다. D/dalvikvm(PID): GC_Reason Amount_freed, Heap_stats, External_memory_stats, Pause_time 예: D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2msGC Reason(GC 이유)GC를 트리거한 이유와 가비지 컬렉션의 종류에 관한 설명입니다. 나타날 수 있는 이유는 다음과 같습니다. GC_CONCURRENT 힙이 가득 차기 시작하면 메모리를 해제하는 동시 GC입니다.GC_FOR_MALLOC 힙이 이미 가득 찼을 때 앱이 메모리 할당을 시도했기 때문에 GC가 발생한 것이므로 시스템이 앱을 중지하고 메모리를 회수해야 했습니다.GC_HPROF_DUMP_HEAP 힙을 분석하기 위해 HPROF 파일 생성을 요청할 때 발생하는 GC입니다.GC_EXPLICIT gc() 를 호출하는 것과 같은 명시적인 GC입니다(필요할 때 GC가 실행될 것을 신뢰하고 이러한 함수 호출을 피해야 함).GC_EXTERNAL_ALLOC API 수준 10 이하에서만 발생하는 GC입니다(그 이상의 버전에서는 Dalvik 힙에서 모든
메모리를 할당함). 외부에서 할당된 메모리를 위한 GC입니다(예: 네이티브 메모리 또는 NIO 바이트 버퍼에 저장되는 픽셀 데이터).Amount freed(회수한 메모리 크기)이 GC를 통해 회수한 메모리의 크기입니다.Heap stats(힙 통계)힙에서 회수한 비율로, (라이브 객체 수)/(총 힙 크기)로 계산됩니다.External memory stats(외부 메모리 통계)API 수준 10 이하에서 외부 할당된 메모리로, (할당된 메모리의 크기)/(컬렉션이 발생하게 되는 한계)입니다.Pause time(일시중지 횟수)힙이 클수록 일시중지 횟수가 많아집니다. 동시 일시중지 횟수는 두 번의 일시중지를 표시하는데, 하나는 컬렉션의 시작 시점이고 다른 하나는 종료 시점 근처입니다.이러한 로그 메시지가 누적되는 동안 힙
통계에서 증가하는 부분이 있는지 찾아보세요(위 예에서는 ART 로그 메시지Dalvik과 달리, ART는 GC를 명시적으로 요청하지 않으면 GC에 관한 메시지를 로그에 기록하지 않습니다. GC는 GC가 느리다고 판단될 때만 출력됩니다. 정확히 말하자면, GC 일시중지가 5ms를 초과하거나 GC 시간이 100ms를 초과하는 경우입니다. 앱이 눈에 띌 정도로 일시중지된 상태가 아니라면(예: 앱이 백그라운드에서 실행 중이거나 사용자가 GC 일시중지 상태를 인식하지 못하는 경우) 앱의 GC는 느리다고 판단되지 않습니다. 명시적 GC는 항상 로그에 기록됩니다. ART는 가비지 컬렉션 로그 메시지에 다음 정보를 포함합니다. I/art: GC_Reason GC_Name Objects_freed(Size_freed) AllocSpace Objects, Large_objects_freed(Large_object_size_freed) Heap_stats LOS objects, Pause_time(s) 예: I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace objects, 21(416KB) LOS objects, 33% free, 25MB/38MB, paused 1.230ms total 67.216msGC Reason(GC 이유)GC를 트리거한 이유와 가비지 컬렉션의 종류에 관한 설명입니다. 나타날 수 있는 이유는 다음과 같습니다. Concurrent 앱 스레드를 정지하지 않는 동시 GC입니다. 이 GC는 백그라운드 스레드에서 실행되며 메모리 할당을 막지 않습니다.Alloc 힙이 이미 가득 찼을 때 앱이 메모리 할당을 시도했기 때문에 이 GC가 시작되었습니다. 이 경우에는 가비지 컬렉션이 할당 스레드에서 발생합니다.Explicit 앱이 가비지 컬렉션을 명시적으로 요청했습니다(예: gc() 또는 gc() 호출). Dalvik과 마찬가지로, ART에서는 가급적 GC를 신뢰하고 GC를 명시적으로 요청하지 않는 것이 권장사항입니다. 명시적 GC는 할당 스레드를 차단하고 불필요하게 CPU 사이클을 낭비하므로 사용하지 않는 것을 권장합니다. 명시적인 GC로 인해 다른 스레드가
선점될 경우에는 버벅거림(앱의 끊김, 떨림 또는 중단)이 발생할 수도 있습니다.NativeAlloc Bitmap 또는 RenderScript 할당 객체와 같은 네이티브 할당에 따른 네이티브 메모리 압력으로 인해 발생한 가비지 컬렉션입니다.CollectorTransition 이 가비지 컬렉션은 힙 전환에 의해 발생하며 힙 전환은 런타임에 GC 전략을 변경하여 발생합니다(예: 눈에 띄는 일시중지 상태 사이에 앱이 변경되는 경우). 가비지 컬렉터 전환은 사용 가능 목록으로 지정된 공간에서 범프 포인터 공간으로(또는 그 반대로) 모든 객체를 복사하도록 구성됩니다. Android 8.0 이전의 RAM 사양이 낮은 기기에서 앱이 포그라운드에서 실행 중인데도 사용자가 GC 일시중지를 인식할 수 있을 정도로 눈에 띄는 일시중지 상태에서 인식할 수 없는 일시중지 상태로(혹은 그 반대) 프로세스 상태를 변경할 때 가비지 컬렉터 전환이 발생합니다. HomogeneousSpaceCompact 같은 종류의 공간 압축은 사용 가능 목록 공간 간의 압축으로, 보통 앱이 일시중지를 인식할 수 없는 프로세스 상태로 이동할 때 발생합니다. 이 작업을 하는 주된 이유는 RAM 사용량을 줄이고 힙 조각 모음을 하기 위해서 입니다. DisableMovingGc 실제 GC 이유는 아니지만, 동시 힙 압축이 이루어지는 동안 GetPrimitiveArrayCritical을 사용했기 때문에 가비지 컬렉션이 차단되었다는 점에 주의해야 합니다. 일반적으로, GetPrimitiveArrayCritical은 가비지 컬렉터 이동을 제한하므로 사용하지 않을 것을 적극적으로 권장합니다. HeapTrim GC 이유는 아니지만, 힙 트림을 마칠 때까지 가비지 컬렉션이 차단된다는 점에 주의해야 합니다.GC Name(GC 이름)ART에서는 여러 가지 다양한 GC를
실행할 수 있습니다.Concurrent mark sweep (CMS) 이미지 공간을 제외한 모든 공간을 회수하고 수집하는 완전한 힙 컬렉터입니다.Concurrent partial mark sweep 이미지 및 zygote 공간을 제외한 모든 공간을 수집하는 거의 완전한 힙 컬렉터입니다.Concurrent sticky mark sweep 마지막 GC 이후로 할당된 객체만 회수할 수 있는 세대 간 컬렉터입니다. 이 가비지 컬렉션이 더 빠르고 일시중지 횟수도 적으므로 전체 또는 부분 마크 스윕보다 더 자주 실행됩니다. Marksweep + semispace 힙 조각 모음을 위한 같은 종류의 공간 압축뿐 아니라 힙 전환에도 사용되는 비동시 방식의 복사 GC입니다.Objects freed(회수한 객체 수)크지 않은 객체 공간에서 이 GC를 통해 회수한 객체의 수입니다.Size freed(회수한 공간의 크기)크지 않은 객체
공간에서 이 GC를 통해 회수한 바이트 수입니다.Large objects freed(회수한 큰 객체 수)이 가비지 컬렉션으로 회수한 큰 객체 공간에 있는 객체 수입니다.Large object size freed(회수한 큰 객체의 크기)이 가비지 컬렉션으로 회수한 큰 객체 공간에 있는 바이트 수입니다.Heap stats(힙 통계)회수한 비율로, (라이브 객체 수)/(총 힙 크기)로 계산됩니다.Pause times(일시중지 횟수)일반적으로 일시중지 횟수는 GC 실행 중에 수정한 객체 참조의 개수에 비례합니다. 현재 ART CMS GC는 GC 종료 시점 근처에서 한 번만 일시중지됩니다. 이동 GC에는 GC 지속 시간 중 대부분의 시간 동안 지속하는 긴 일시중지가 있습니다.Logcat에 다량의 GC가 있는 경우 힙 통계에서 증가하는 부분을
찾아보세요(위 예에서는 Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates. Last updated 2022-07-13 UTC. [{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"필요한 정보가 없음" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"너무 복잡함/단계 수가 너무 많음" },{ "type": "thumb-down", "id": "outOfDate", "label":"오래됨" },{ "type": "thumb-down", "id": "translationIssue", "label":"번역 문제" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"샘플/코드 문제" },{ "type": "thumb-down", "id": "otherDown", "label":"기타" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"이해하기 쉬움" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"문제가 해결됨" },{ "type": "thumb-up", "id": "otherUp", "label":"기타" }] |