안드로이드 로그캣 구경하기

Lee Yongin·2022년 2월 1일
0

안드로이드

목록 보기
2/12
post-thumbnail

1.서론

안드로이드는 참 다양한 방법으로 레이아웃을 보여주지 않을 때가 있다.
그래서 디버깅 로그를 봤는데 몇 백줄은 되는 것 같았다.
그 많은 정보들 가운데 딱 보기에 부정적인(?) 메세지들은 아래와 같다.
뭔가 실패했다 지원이 안된다 포화상태다

I/System.out: waiting for debugger to settle...
W/System: A resource failed to call close. 
(중략)
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
I/Gralloc4: mapper 4.x is not supported
I/Choreographer: Skipped 43 frames!  The application may be doing too much work on its main thread.

여태껏 자세히 본 적이 없어서 몇 개 구경(?)해보았다

2. 본론

어떻게든 코드만 돌아가게끔 만드느라 로그캣(LogCat)에 나오는 로그가 어떤 의미인지 모르고 있었다.인터넷에 검색한 키워드가 너무 많아서 정리를 하는 시리즈가 될 것 같다.

I/e.myapplicatio:
I/chatty:
I/System.out:
I/Choreographer:
I/Gralloc4:
I/OpenGLRenderer:

W/e.myapplicatio:
W/System:
W/OpenGLRenderer:

V/studio.deploy:

D/NetworkSecurityConfig:
D/libEGL:
D/HostConnection:
D/EGL_emulation:
D/goldfish-address-space:

로그 레벨 설정이라는 게 있었다

Verbose(상세): 모든 로그 메시지를 표시합니다(기본 설정).
Debug(디버그): 개발 단계에서만 유용한 디버그 로그 메시지뿐 아니라 그보다 낮은 레벨의 메시지도 이 목록에 표시합니다.
Info(정보): 일반적인 사용을 위해 예상할 수 있는 로그 메시지뿐 아니라 그보다 낮은 레벨의 메시지도 이 목록에 표시합니다.
Warn(경고): 아직 오류는 아니지만 발생할 수 있는 문제뿐 아니라 그보다 낮은 레벨의 메시지도 이 목록에 표시합니다.
Error(오류): 오류를 일으킨 문제뿐 아니라 그보다 낮은 레벨의 메시지도 이 목록에 표시합니다.
Assert(강제종료): 개발자가 발생해서는 안 된다고 생각하는 문제를 표시합니다.

로그가 대체적으로 어떤 상황을 뜻하는지 간단히 확인하거나, 몰랐던 안드로이드 요소들을 정리해보았다.

1.안드로이드의 JNI

I/e.myapplicatio: Late-enabling -Xcheck:jni

안드로이드 앱은 전적으로 Dalvik 위에서 실행되지만, 일부는 Android NDK를 사용한다. JNI를 사용하는 네이티브 코드를 포함하기 위한 것이다. JNI는 다루기 어렵고, 개발자는 이와 관련된 콘솔의 충돌보고에 대해 자세히 알 필요가 없기 때문에 CheckJNI라는 프로그램으로 Android JNI 디버깅을 하고 있다. 단순히 Android JNI가 늦게 활성화되었다는 메세지인 것 같다.
(출처)https://android-developers.googleblog.com/2011/07/debugging-android-jni-with-checkjni.html

2.파일 최적화과정

I/e.myapplicatio: Unquickening 12 vdex files!

VDEX 파일은 안드로이드 운영체제에서 안드로이드 앱의 로드 시간을 단축하기 위해 생성한 것이다. VDEX 파일에는 이전에 검증된 DEX(Dalvik Executive) 파일의 최적화된 버전이 포함되어 있으며, 안드로이드는 앱을 다시 컴파일할 때 이 파일의 압축을 다시 풀고 다시 검증할 필요가 없기 때문이다.
(Android Oreo(8.0.0)이후의 과정)

위의 그림을 참고해 보면, java 코드를 Dalvik 코드로 변환하는 것이 APK 빌드 프로세스 과정이다. DEX로 완성된 코드는 dex2oat 변환을 통해 생성된 OAT와 VDEX 파일로 바뀐다.
아래의 그림은 안드로이드 오레오8.1.0 에 적용된 VDEX10의 내부 구조이다. 맨 밑의 Quickening Info라고 하는 부분은 바이트코드 최적화 동안 적용된 dex간 변환을 되돌리기 위해 요구되는 데이터들이다.
'UnQuicken' 이 정확히 어떤 표현인지 생각해보자면, 'The Vdex fully unquickened functionality is implented...'라는 걸로 보아 '전체 libar를 빌드할 필요가 없는 상태로 만드는 기능의 과정' 인 것 같다. Quicken은 반대로 dex 변환을 되돌리는 것이고...

이 과정에서 필요한 아이디어 및 도구가 'Bytecode Unquickening Decomplier'이고, dex 간 변환을 하기 위해 전체 libart 빌드가 필요없는 독립적인 도구이다.
결국 Unquickening 12 vdex files라는 메세지는 Dex파일이 Vdex파일로 최적화 되었다 라는 뜻인 것 같다.

(출처)
https://fileinfo.com/extension/vdex
https://lief-project.github.io/doc/latest/tutorials/10_android_formats.html#oat-and-vdex
https://www.romainthomas.fr/post/android-vdex/
https://github.com/anestisb/vdexExtractor

3.Java Garbage Collector

I/e.myapplicatio: WaitForGcToComplete blocked RunEmptyCheckpoint on ProfileSaver for 11.077ms

Gc는 Java가 메모리를 정리하기 위해 사용하는 도구, Garbage Collection을 의미한다.
C나 C++은 직접 메모리를 해제하지만 Java는 JVM이 가비지 컬렉션을 이용해 사용하지 않는 객체의 메모리를 없애주는 메모리 관리를 해준다.
이를 담당하는 알고리즘을 세대별 가비지 컬렉션(Generational garbage collection)이라고 한다. 힙 메모리를 2부분, Young generation이 있는 Nusery area와 Old generation이 있는 Tenure area로 나누어 관리한다.

우선 Young generation의 object들의 가비지 컬렉션 흐름을 보면 아래와 같다.
Step1. 새로 할당되는 객체는 Eden에 쌓이고, 이 공간이 꽉 차면 Minor 가비지 컬렉션이 수행된다. 더 이상 사용하지 않는 객체들을 버리고 나머지는 Survivor S0에 쌓이는 것이다. 이로써 Eden과 S1은 빈 공간이 된다.
Step2. Eden이 다시 꽉 차면 Survivor S0와 Eden의 사용하지 않는 객체들을 버리고 나머지를 Survivor S1으로 이동시킨다. 이로써 Eden과 S0은 빈 공간이 된다.
Step3. S1에 있던 모든 객체들을 다시 S0으로 보낸다.
Step4. Step2와 Step3를 반복해서 객체의 tenure age가 꽉 차면 tenure space으로 객체를 이동시킨다.

위의 단계를 거친 tenure area의 오래된 객체들에는 major garbage collection, full garbage collection이 수행된다. 중요한 건 이 작업을 수행할 때 새 객체를 할당하는 것을 방지하고, 기존객체와 연결되지 못하게 애플리케이션의 동작이 중지된다.
가끔 이러한 full collection 이벤트가 자주 일어나는 경우 애플리케이션 요청처리가 저하되기도 한다. 이와 관련해서 break point가 너무 많으면 뜨는 메세지, 'Waiting for a blocking GC ProfileSaver' 가 있다. GC ProfileSaver가 뭔지 구글링을 해봤지만 시원한 답을 얻진 못했다. 아 몰랑
(출처)
https://developers.redhat.com/articles/2021/08/20/stages-and-levels-java-garbage-collection#
https://developers.redhat.com/articles/2021/09/09/how-jvm-uses-and-allocates-memory#tracking_memory_use_in_the_jvm
https://sematext.com/blog/java-garbage-collection-logs/
https://www.eclipse.org/openj9/docs/gc/

4.안드로이드 Chatty Log Policy

I/chatty: uid=10154(com.example.myapplication) identical 1 line

LogCat에서 로그를 제대로 찍어주지 않는 상황이다. 더 풀어보자면, 로그 버퍼 크기가 정해져있는데, 초당 5줄을 초과할 때, 256KB 로그 버퍼가 다른 로그를 찍어내는데 유지되기 위해서 'Chatty' '수다스러우니까 안 알려줌' 을 출력한 것이다. 이는 보통 256KB 로그 버퍼를 유지하는 이유는 CPU와 배터리 사용률을 제한하기 위해서이다.
Chatty가 발생하는 걸 방지하기 위해서 logcat을 위해 앱을 'whitelisting'할 수 있다고 하는데, 왜 앱을 whitelisting하면 chatty log가 방지되는지 이해가 안 간다...

adb logcat -P '<pid or uid of your app>' 

whitelisting은 컴퓨터 시스템에서 돌아가도록 승인된 애플리케이션을 구분하는 것이고, 잠재적으로 위해한 애플리케이션으로부터 컴퓨터를 보호하는 것이 목적이다. 라고 요약할 수 있는 내용(밑에 일부내용)이 엄청 많지만 구체적으로 왜왜왜 chatty log가 방지되는지 못 찾았다. 내가 찾은 whitelisting이 같은 whitelisting이 아닌가???라는 생각도 해봤는데 그건 아닌 거 같고

Application whitelisting is designed to monitor an OS in real time and prevent the execution of unauthorized files. This goes beyond simply preventing unwanted applications from running. Application whitelisting may also restrict the use of PowerShell scripts and other types of scripts in an effort to prevent ransomware attacks.

그래서 결국 stackoverlfow에 질문을 남겼다 아무도 안 말해줬던 거 보면 너무 당연한 건데 내 전공지식이 부족해서 모르는 걸 수도 있다 ㅎ 능력자들이 답변을 달고 토론을 해주면 좋겠다...

(출처)
https://www.techtarget.com/searchsecurity/definition/application-whitelisting
https://stackoverflow.com/questions/34587273/android-logcat-logs-chatty-module-line-expire-message

5.Chunk와 ExoPlayer library

I/System.out: Sending WAIT chunk

ExoPlayer library에 Chunk라는 추상 기본 클래스라는 것이 존재하는데 이게 이 Chunk를 의미하는 것 같다.

(그 외 Chunk는 '스트림 제어 전송 프로토콜(SCTP)에 사용되는 제어 데이터(C/D) 및 패킷 집합'이라는 설명도 있지만 안드로이드 로그와 거리가 너무 멀어서 제외했다.)
Chunk는 Loader.Loadable 인터페이스를 구현한 추상 클래스이고, 스트림재생이 필요한 데이터를 로드하기 위해 사용한다. 아래와 같이 Chunk를 이루는 필드는 미디어의 종료시간, 로드작업 식별ID, 미디어의 시작시간, Chunk가 속한 트랙의 형식, 청크가 트랙에 속하는 경우 선택이유, 청크의 데이터타입 등 모두 스트림재생에 필요한 필드로 이루어진 걸 볼 수 있다.

이렇게 Chunk를 제공하는 ExoPlayer 라이브러리는 처음 들어봤는데, ExoPlayer는 Android SDK에서 별도로 배포한 오픈소스 프로젝트이다. Android Media Codec API를 기반으로 하고 있고 Android의 MediaPlayer가 현재 지원하지 않는 DASH, SmoothStream 등을 포함하는 기능들을 지원해준다. 또한 앱 개발을 할 때 신경써야 할 주제들과 해결포인트도 제공한다.
밑의 8가지 정도 주제들이 정리되어 있었다.

Digital rights management
Troubleshooting
Customization
Transforming media
Battery consumption
APK shrinking
OEM testing
Design document

예를 들어서 Battery consumption이라는 주제에선 같은 동영상을 재생해도 배터리 사용량을 줄일 수 있는 UI component와 전력사용량 정보를 제공한다.
줄일 수 없다면 배터리 최적화에 우선순위를 둘지, 기능 세트와 신뢰성에 우선순위를 둘지 선택할 수 있도록 도와주는 내용도 있다.
이 외에 Digital rights management, Trobleshooting 등도 있지만 가벼운 배경지식 포스팅말고 내 프로젝트에 적용하고 메인주제로 포스팅하는 게 적절할 듯 하다.

(출처)
https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/source/chunk/Chunk.html#type
https://developer.android.com/guide/topics/media/exoplayer?hl=ko
https://exoplayer.dev/

3.결론

모르는 것들이 참 많이 있었구나...하핳

profile
f1을 좋아하는...🏆 f1처럼 빠르고 정확한 걸 좋아하는 안드로이드 개발자

0개의 댓글