앱 디버그

Android 스튜디오에서 제공하는 디버거를 통해 다음과 같은 작업을 할 수 있습니다.

  • 앱을 디버깅할 기기를 선택합니다.
  • 자바, Kotlin, C/C++ 코드에 중단점을 설정합니다.
  • 런타임에 변수를 검사하고 표현식을 평가합니다.

이 페이지에서는 기본적인 디버거 작업을 안내합니다. 추가 문서는 IntelliJ IDEA 디버깅 문서에서 확인할 수 있습니다.

디버깅 사용 설정하기

디버깅을 시작하려면 다음을 실행하세요.

기기에서 디버깅을 사용 설정합니다.
에뮬레이터를 사용 중이라면 디버깅이 기본적으로 사용 설정되어 있습니다. 하지만 연결된 기기에서는 기기 개발자 옵션에서 디버깅을 사용하도록 설정해야 합니다.
디버그 가능한 빌드 변형을 실행합니다.

빌드 구성에 debuggable true(Kotlin 스크립트에서는 isDebuggable = true)가 포함된 빌드 변형을 사용합니다.

일반적으로 모든 Android 스튜디오 프로젝트에 포함된(build.gradle 파일에서는 보이지 않더라도) 기본 'debug' 변형을 선택할 수 있습니다. 그러나 디버그가 가능해야 하는 새 빌드 유형을 정의하는 경우에는 빌드 유형에 debuggable true를 추가해야 합니다.

Groovy

android {
    buildTypes {
        customDebugType {
            debuggable true
            ...
        }
    }
}

Kotlin

android {
    buildTypes {
        create("customDebugType") {
            isDebuggable = true
            ...
        }
    }
}

이 속성은 C/C++ 코드가 사용된 모듈에도 적용됩니다.

참고: jniDebuggable 속성은 더 이상 사용되지 않습니다.

디버그하려는 라이브러리 모듈에 기반한 앱인 경우 이 라이브러리 또한 디버그 기호를 보유하도록 debuggable true를 포함하여 패키징해야 합니다. 앱 프로젝트의 디버그 가능 변형이 라이브러리 모듈의 디버그 가능 변형을 받도록 하려면 기본 버전 이외의 라이브러리 버전을 게시합니다.

디버깅 시작하기

다음과 같이 디버깅 세션을 시작할 수 있습니다.

  1. 앱 코드에서 중단점을 설정합니다.
  2. 툴바의 대상 기기 메뉴에서 앱을 디버그할 기기를 선택합니다.
    대상 기기 메뉴
    그림 1. 대상 기기 메뉴.

    설정된 기기가 없는 경우 USB를 통해 기기를 연결하거나, Wi-Fi를 통해 기기를 연결하거나, AVD를 생성하여 Android Emulator를 사용해야 합니다.

  3. 툴바에서 Debug 를 클릭합니다.

    앱이 이미 기기에서 실행 중인 경우 Run에서 Debug로 전환할지 묻는 대화상자가 표시됩니다. 디버깅을 시작하려면 기기를 다시 시작해야 합니다. 실행 중인 앱 인스턴스를 그대로 유지하려면 Cancel Debug를 클릭한 후 실행 중인 앱에 디버거를 연결합니다. 그러지 않으면 Android 스튜디오에서 APK를 빌드하고 디버그 키로 서명한 후 선택한 기기에 APK를 설치하고 실행합니다.

    C 코드 및 C++ 코드를 프로젝트에 추가하면 Android 스튜디오는 Debug 창에서 LLDB 디버거를 실행하여 네이티브 코드도 디버그합니다.

  4. Debug 창이 열려 있지 않으면 View > Tool Windows > Debug를 선택하거나 도구 창 모음에서 Debug 를 클릭합니다.

실행 중인 앱에 디버거 연결하기

앱이 이미 기기에서 실행 중인 경우 다음과 같은 방법을 사용하면 앱을 다시 시작하지 않고도 디버깅을 시작할 수 있습니다.

  1. Attach debugger to Android process 를 클릭합니다.
  2. Choose Process 대화상자에서 디버거와 연결할 프로세스를 선택합니다.
    1. 에뮬레이터나 루팅된 기기를 사용 중인 경우 Show all processes를 선택하여 모든 프로세스를 표시할 수 있습니다. 루팅된 기기에서는 기기에서 실행 중인 모든 프로세스가 표시됩니다. 그러나 루팅되지 않은 기기에서는 디버그 가능한 프로세스만 표시됩니다.
    2. Use Android Debugger Settings from 메뉴에서 기존 실행/디버그 구성을 선택할 수 있습니다. C 및 C++ 코드의 경우 이렇게 하면 기존 구성에서 LLDB 시작 명령어, LLDB 게시/연결 명령어, 기호 디렉터리를 재사용할 수 있습니다.
    3. 기존의 실행/디버그 구성이 없으면 Create New를 선택합니다. 이렇게 하면 Debug Type 메뉴가 사용 설정되고 여기서 다른 디버그 유형을 선택할 수 있습니다. 기본적으로 Android 스튜디오는 Detect Automatically 디버그 유형을 사용하여 프로젝트에 Java 코드가 포함되었는지 C/C++ 코드가 포함되었는지에 따라 최적의 디버거 옵션을 선택합니다.
  3. OK를 클릭합니다.

    Debug 창이 나타납니다.

Device Explorer의 프로세스 탭(View > Tool Windows > Device Explorer)에는 디버그 가능한 프로세스 목록도 있습니다. 그런 다음 프로세스를 선택하고 종료 , 강제 종료 또는 디버거를 특정 프로세스에 첨부 합니다.

디버그 창

그림 2. 디버그 창

디버그 창은 다음과 같이 구성됩니다.

  1. 실행 및 탐색 툴바. 중단점 사용을 참고하세요.
  2. 스레드 선택기
  3. 평가 및 watch 표현식 항목. 변수 검사를 참고하세요.
  4. 스택 디스플레이
  5. 변수 창. 변수 검사를 참고하세요.

참고: Android 스튜디오 디버거와 가비지 컬렉터는 느슨하게 통합됩니다. Android 가상 머신은 디버거 연결이 해제되기 전까지는 디버거가 인식하는 어떠한 객체에도 가비지 컬렉션이 발생하지 않도록 보장합니다. 이로 인해, 디버거가 연결되어 있는 동안에는 객체가 누적될 수 있습니다. 예를 들어 실행 중인 스레드를 디버거가 발견하면 이 스레드가 종료되었더라도 디버거 연결이 해제될 때까지는 연결된 Thread 객체에 가비지 컬렉션이 발생하지 않습니다.

디버거 유형 변경하기

Java/Kotlin 코드와 C/C++ 코드를 디버그하는 데는 서로 다른 디버거 도구가 필요하므로 Android 스튜디오 디버거에서는 사용할 디버거 유형을 선택할 수 있습니다. 기본적으로 Android 스튜디오는 Detect Automatically 디버거 유형을 사용하여, 프로젝트에서 감지되는 언어에 따라 사용할 디버거를 결정합니다.

디버그 구성에서 디버거를 수동으로 선택하려면 Run > Edit Configurations를 클릭합니다. Run > Attach debug to Android process를 클릭하여 표시되는 대화상자에서 디버거를 선택할 수도 있습니다.

사용할 수 있는 디버그 유형에는 다음이 포함됩니다.

Detect Automatically
디버깅 중인 코드에 가장 적합한 옵션을 Android 스튜디오에서 자동으로 선택하게 하려면 이 디버그 유형을 선택합니다. 예를 들어 프로젝트에 C 코드나 C++ 코드가 있다면 Android 스튜디오에서 자동으로 Dual 디버그 유형을 사용하고 그렇지 않은 경우에는 Java-Only 디버그 유형을 사용합니다.
Java Only
자바 또는 Kotlin으로 작성된 코드만 디버그하려면 이 디버그 유형을 선택합니다. 자바 전용 디버거는 네이티브 코드에 설정한 중단점이나 watchpoint를 무시합니다.
Native Only(C/C++ 코드에서만 사용 가능)
LLDB만 사용하여 코드를 디버그하려면 이 디버그 유형을 선택합니다. 이 디버그 유형을 사용할 경우에는 자바 디버거 세션 뷰를 사용할 수 없습니다. 기본적으로, LLDB는 네이티브 코드만 검사하며 Java 코드 내의 중단점을 무시합니다. Java 코드도 디버그하려면 Detect Automatically 또는 Dual 디버그 유형으로 전환하세요.

네이티브 디버깅은 다음 요구사항을 충족하는 기기에서만 작동합니다.

  • 이 기기는 run-as를 지원합니다.

    기기가 run-as를 지원하는지 확인하려면 기기에 연결된 ADB 셸에서 다음 명령어를 실행합니다.

    run-as your-package-name pwd
    

    your-package-name을 앱의 패키지 이름으로 바꿉니다. 기기에서 run-as를 지원하면 명령어는 오류 없이 반환되어야 합니다.

  • 기기에서 ptrace가 사용 설정되어 있습니다.

    ptrace가 사용 설정되어 있는지 확인하려면 기기에 연결된 ADB 셸에서 다음 명령어를 실행합니다.

    sysctl kernel.yama.ptrace_scope
    

    ptrace가 사용 설정되어 있으면 명령어는 0 값이나 unknown key 오류를 출력합니다. ptrace가 사용 설정되어 있지 않으면 명령어는 0 이외의 값을 출력합니다.

Dual(Java + 네이티브)(C/C++ 코드에서만 사용 가능)
Java와 네이티브 코드 디버깅 간에 전환하려면 이 디버그 유형을 선택합니다. Android 스튜디오는 자바 디버거와 LLDB 모두를 앱 프로세스에 연결하므로, 앱을 다시 시작하거나 디버그 구성을 변경하지 않고도 자바 코드와 네이티브 코드 모두에서 중단점을 검사할 수 있습니다.

그림 2에서는 Debug라는 창 제목의 오른쪽에 있는 탭 두 개를 볼 수 있습니다. 앱에 자바 코드와 C++ 코드가 모두 있으므로 한 탭은 네이티브 코드 디버깅용이고 다른 하나는 -java로 표시된 자바 코드 디버깅용입니다.

그림 3. 네이티브 코드 디버깅용 탭과 자바 코드 디버깅용 탭.

참고: 컴파일러에 의해 최적화된 네이티브 코드를 디버깅하는 경우 다음과 같은 경고 메시지가 나타날 수도 있습니다.
This function was compiled with optimizations enabled. Some debugger features may not be available 최적화 플래그를 사용하는 경우 컴파일러에서 컴파일된 코드를 변경하여 더 효율적으로 실행되도록 합니다. 이에 따라 디버거에서 최적화된 컴파일 코드를 다시 원래 소스 코드에 매핑하기가 어려워지므로 디버거가 예기치 않은 정보나 잘못된 정보를 신고할 수 있습니다. 이런 이유로, 네이티브 코드를 디버그할 때는 컴파일러 최적화를 사용 중지해야 합니다.

시스템 로그 사용하기

시스템 로그는 앱을 디버그하는 중에 시스템 메시지를 표시합니다. 이 메시지에는 기기에서 실행 중인 앱의 정보가 포함됩니다. 시스템 로그를 사용하여 앱을 디버그하려면 앱의 개발 단계에서 코드에 로그 메시지를 쓰고 예외의 스택 트레이스를 출력해야 합니다.

코드에 로그 메시지 쓰기

코드에 로그 메시지를 쓰려면 Log 클래스를 사용합니다. 로그 메시지는 개발자가 앱과 상호작용할 때 시스템 디버그 출력을 수집하여 실행 흐름을 이해하도록 도와줍니다. 또한 앱의 어떤 부분이 실패했는지도 알려줍니다. 로깅에 관한 자세한 내용은 Logcat을 이용한 로그 작성 및 보기를 참고하세요.

다음 예시는 개발자의 활동이 시작될 때 이전 상태 정보의 사용 가능 여부를 결정하기 위해 로그 메시지를 추가하는 방법을 보여줍니다.

Kotlin

import android.util.Log
...
class MyActivity : Activity() {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        if (savedInstanceState != null) {
            Log.d(TAG, "onCreate() Restoring previous state")
            /* restore state */
        } else {
            Log.d(TAG, "onCreate() No saved state available")
            /* initialize app */
        }
        ...
    }
  ...
  companion object {
    private val TAG: String = MyActivity::class.java.simpleName
    ...
  }
}

Java

import android.util.Log;
...
public class MyActivity extends Activity {
    private static final String TAG = MyActivity.class.getSimpleName();
    ...
    @Override
    public void onCreate(Bundle savedInstanceState) {
       ...
       if (savedInstanceState != null) {
            Log.d(TAG, "onCreate() Restoring previous state");
            /* restore state */
        } else {
            Log.d(TAG, "onCreate() No saved state available");
            /* initialize app */
        }
        ...
    }
}

또한 개발 중에 코드에서 예외를 포착하고 스택 트레이스를 시스템 로그에 쓸 수 있습니다.

Kotlin

fun someOtherMethod() {
    try {
        ...
    } catch (e : SomeException) {
        Log.d(TAG, "someOtherMethod()", e)
    }
}

Java

void someOtherMethod() {
    try {
        ...
    } catch (SomeException e) {
        Log.d(TAG, "someOtherMethod()", e);
    }
}

참고: 앱을 게시할 준비가 되면 디버그 로그 메시지와 스택 트레이스 출력 호출을 코드에서 삭제하세요. DEBUG 플래그를 설정하고 디버그 로그 메시지를 조건문에 넣으면 삭제됩니다.

시스템 로그 보기

그림 4와 같이 Logcat 창에서 디버그 메시지와 기타 시스템 메시지를 보고 필터링할 수 있습니다. 예를 들어 가비지 컬렉션이 발생할 때 표시되는 메시지 또는 Log 클래스를 사용하여 앱에 추가하는 메시지를 확인할 수 있습니다.

Logcat을 사용하려면 디버깅을 시작하고 Logcat 탭을 선택합니다.

그림 4. 필터 설정이 있는 Logcat 창.

Logcat 및 Logcat 필터링 옵션에 관한 자세한 설명은 Logcat을 이용한 로그 작성 및 보기를 참고하세요.

중단점 사용하기

Android 스튜디오는 다양한 디버깅 작업을 트리거하는 중단점을 지원합니다. 중단점 유형에는 몇 가지가 있습니다.

줄 중단점
가장 일반적인 유형은 지정된 코드 줄에서 앱 실행을 일시중지하는 줄 중단점입니다. 일시중지된 상태에서 변수를 검사하고 표현식을 평가한 다음, 한 줄씩 실행을 계속하여 런타임 오류의 원인을 판별할 수 있습니다.
메서드 중단점
메서드 중단점은 특정 메서드로 전환되거나 특정 메서드에서 나갈 때 앱의 실행을 일시중지합니다. 일시중지된 상태에서 변수를 검사하고 표현식을 평가한 다음, 한 줄씩 실행을 계속하여 런타임 오류의 원인을 판별할 수 있습니다. 구성 가능한 함수에 중단점을 설정하면 디버거는 컴포저블의 매개변수와 상태를 나열하여 어떤 변경사항이 리컴포지션을 유발했을 수 있는지 식별하는 데 도움을 줍니다.
필드 중단점
필드 중단점은 앱이 특정 필드에서 읽거나 특정 필드에 쓸 때 앱의 실행을 일시중지합니다.
예외 중단점
예외 중단점은 예외가 발생할 때 앱 실행을 일시중지합니다.

특정 조건이 충족되는 경우에만 실행을 정지하는 조건부 중단점을 설정할 수 있습니다. 실행을 정지하지 않고 Logcat에 쓰는 로깅 중단점을 설정할 수도 있습니다. 이를 통해 코드에 로그 구문을 포함하는 것을 방지할 수 있습니다.

줄 중단점을 추가하려면 다음 단계를 진행하세요.

  1. 실행을 일시중지하려는 코드 줄을 찾습니다.
  2. 이 코드 줄의 왼쪽 여백을 클릭하거나 줄에 캐럿을 두고 Control+F8(macOS에서는 command+F8)을 누릅니다.
  3. 앱이 이미 실행 중인 경우 Attach debug to Android process 를 클릭합니다. 실행되고 있지 않은 경우에 디버깅을 시작하려면 Debug 를 클릭합니다.

중단점을 설정하면 그림 5와 같이 줄 옆에 빨간색 점이 표시됩니다.

그림 5. 중단점을 설정하면 줄 옆에 빨간색 점이 표시됩니다.

코드 실행이 중단점에 도달하면 Android 스튜디오가 앱 실행을 일시중지합니다.

앱 상태를 확인하려면 Debugger 탭의 도구를 사용합니다.

  • 변수의 객체 트리를 검사하려면 Variables 뷰에서 트리를 펼칩니다. Variables 뷰가 표시되지 않으면 Layout Settings 를 클릭하고 variables가 선택되었는지 확인합니다.

  • 메서드를 입력하지 않고 코드의 다음 줄로 이동하려면 Step Over 를 클릭합니다.

  • 메서드 호출 내의 첫 줄로 이동하려면 Step Into 를 클릭합니다.

  • 현재 메서드 밖의 다음 줄로 이동하려면 Step Out 을 클릭합니다.

  • 정상적으로 앱 실행을 계속하려면 Resume Program 을 클릭합니다.

프로젝트에서 네이티브 코드를 사용하는 경우 기본적으로 Detect Automatically 디버그 유형에서는 Java 디버거와 LLDB 모두를 별도의 두 프로세스로 앱에 연결합니다. 앱을 다시 시작하거나 설정을 변경하지 않고도 자바 및 C/C++ 중단점 간에 검사를 전환할 수 있습니다.

참고: Android 스튜디오가 C 코드나 C++ 코드에서 중단점을 감지하도록 하려면 LLDB를 지원하는 디버그 유형을 사용해야 합니다(예: Detect Automatically, Native 또는 Dual). 디버그 구성을 수정하여 Android 스튜디오가 사용하는 디버그 유형을 변경할 수 있습니다. 다른 디버그 유형에 관해 자세히 알아보려면 다른 디버그 유형 사용에 관한 섹션을 참조하세요.

Android 스튜디오가 앱을 대상 기기에 배포할 때, Debug 창이 열리고 이 창에는 각 디버거 프로세스별로 탭이나 디버그 세션 뷰가 표시됩니다(그림 6 참고).

그림 6. LLDB를 사용한 네이티브 코드 디버깅.
  1. Android 스튜디오는 LLDB 디버거가 C/C++ 코드에서 중단점에 도달하면 <your-module> 탭으로 전환됩니다. Frames, Variables, Watches 창도 사용할 수 있으며 이러한 창은 자바 코드를 디버깅할 때와 똑같은 방식으로 작동합니다.

    Threads 창을 LLDB 세션 뷰에서 사용할 수는 없지만 Frames 창의 목록을 사용하여 앱 프로세스에 액세스할 수 있습니다. 이 창에 관한 자세한 내용은 창 프레임 디버그 방법 및 변수 검사 방법을 설명하는 섹션을 참고하세요.

    참고: 네이티브 코드의 중단점을 검사하는 중에 Android 시스템에서는 앱의 자바 바이트코드를 실행하는 가상 머신을 정지합니다. 즉, 네이티브 코드의 중단점을 검사하는 동안에는 자바 디버거와 상호작용할 수 없거나 자바 디버거 세션에서 상태 정보를 검색할 수 없습니다.

  2. Android 스튜디오는 자바 디버거가 자바 코드 또는 Kotlin 코드에서 중단점에 도달하면 <your-module>-java 탭으로 전환됩니다.
  3. LLDB로 디버깅하는 동안 LLDB 세션 뷰의 LLDB 터미널을 사용하여 명령줄 옵션을 LLDB로 전달할 수 있습니다. 앱 디버깅을 시작할 때마다 LLDB에서 실행하도록 할 특정 명령어가 있다면 디버거가 앱 프로세스에 연결되기 직전이나 연결된 직후에 명령어를 디버그 구성에 추가하면 됩니다.

C/C++ 코드를 디버깅하는 중에는 watchpoint라는 특수 유형의 중단점을 설정할 수도 있습니다. watchpoint는 앱이 메모리의 특정 블록과 상호작용할 때 앱 프로세스를 정지할 수 있습니다. 자세히 알아보려면 watchpoint 추가 방법을 설명하는 섹션을 참조하세요.

중단점 보기 및 구성

모든 중단점을 보고 중단점 설정을 구성하려면 Debug 창에서 View Breakpoints 를 클릭합니다. 그림 7과 같이 Breakpoints 창이 표시됩니다.

그림 7. 현재 중단점이 모두 나와 있고 각 중단점의 동작 설정이 포함된 Breakpoints 창

Breakpoints 창에 있는 목록에서 각 중단점을 사용 설정하거나 중지할 수 있습니다. 중단점을 사용 중지하면 Android 스튜디오는 이 중단점에 도달하더라도 앱을 일시중지하지 않습니다.

설정을 구성할 중단점을 목록에서 선택합니다. 처음에 중단점을 사용 중지하고 다른 중단점에 도달한 후에 시스템이 중단점을 사용 설정하도록 구성할 수 있습니다. 또한 중단점에 도달한 후 중단점의 사용 중지 여부를 구성할 수도 있습니다. 예외에 중단점을 설정하려면 중단점 목록에서 Exception Breakpoints를 선택합니다.

모든 중단점을 일시적으로 사용 중지하려면 디버그 창에서 Mute Breakpoints 를 클릭합니다. 다시 사용 설정하려면 다시 클릭하세요.

창 프레임 디버그

Debugger 창에 있는 Frames 창에서는 현재 중단점에 이르도록 한 스택 프레임을 검사할 수 있습니다. 이렇게 하면 스택 프레임을 탐색하고 검토할 수 있으며 또한 Android 앱의 스레드 목록을 검사할 수도 있습니다.

스레드를 선택하려면 스레드 선택기 메뉴를 사용하여 스택 프레임을 표시합니다. 프레임의 요소를 클릭하여 편집기에서 소스를 엽니다. 프레임 검토 가이드의 설명대로 스레드 표현을 맞춤설정하고 스택 프레임을 내보낼 수도 있습니다.

변수 검사하기

Debugger 창에 있는 Variables 창에서는 시스템이 중단점에서 앱을 중지할 때 변수를 검사할 수 있으며 Frames 창에서는 프레임을 선택할 수 있습니다. 또한 Variables 창을 사용하면 선택한 프레임 내에서 사용 가능한 정적 메서드 또는 변수를 사용하여 임시 표현식을 평가할 수 있습니다.

애플리케이션이 디버깅되는 동안 객체 트리에 표현식을 추가하려면 다음 안내를 따르세요.

그림 8. 디버그 창의 객체 트리 및 표현식 항목 상자
  1. 감시하거나 표시할 표현식을 입력합니다.
  2. Add to watches를 클릭하거나 Enter를 눌러 표현식을 한 번 평가합니다.

또는 객체 트리에 감시하려는 표현식이 포함되어 있다면 트리 상단으로 드래그하여 감시 표현식으로 추가할 수 있습니다.

중단점에 도달하거나 코드를 단계별로 실행하면 감시 표현식이 업데이트됩니다.

평가된 표현식은 다른 표현식을 수동으로 평가하거나 코드를 단계별로 실행할 때까지 객체 트리 상단에 계속 표시됩니다.

객체 트리에서 감시 표현식을 삭제하려면 표현식을 마우스 오른쪽 버튼으로 클릭한 다음 Remove Watch를 클릭합니다.

감시점 추가

C/C++ 코드를 디버깅하는 중에는 watchpoint라는 특수 유형의 중단점을 설정할 수 있습니다. watchpoint는 앱이 메모리의 특정 블록과 상호작용할 때 앱 프로세스를 중지할 수 있습니다. 예를 들어 두 개의 포인터를 메모리 블록에 설정하고 여기에 watchpoint를 할당한 경우 두 포인터 중 하나를 사용하여 메모리 블록에 액세스하면 이 watchpoint가 트리거됩니다.

Android 스튜디오에서 런타임 중에 특정 변수를 선택하여 watchpoint를 만들 수 있지만, LLDB는 변수 자체가 아니라 시스템이 변수에 할당한 메모리 블록에만 watchpoint를 할당합니다. 이는 Watches 창에 변수를 추가하는 것과는 다릅니다. 이 경우에는 변수 값을 관찰할 수 있지만 시스템이 메모리의 값을 읽거나 변경할 때는 앱 프로세스를 중단할 수 없습니다.

참고: 앱 프로세스가 함수를 종료하고 시스템이 메모리에서 로컬 변수 할당을 해제하는 경우, 이들 변수별로 생성했던 watchpoint를 다시 할당해야 합니다.

감시점을 설정하려면 다음 요구사항을 충족해야 합니다.

  • 대상 실제 기기나 에뮬레이터가 x86 또는 x86_64 CPU를 사용합니다. 기기가 ARM CPU를 사용하는 경우 메모리에서 변수 주소의 경계를 4바이트(32비트 프로세서) 또는 8바이트(64비트 프로세서)로 정렬해야 합니다. 네이티브 코드에서 변수를 정렬하려면 아래와 같이 변수 선언부에 __attribute__((aligned(num_bytes)))를 지정합니다.
    // For a 64-bit ARM processor
    int my_counter __attribute__((aligned(8)));
    
  • 이미 watchpoint를 세 개 이하 할당했습니다. Android 스튜디오는 x86 또는 x86_64 대상 기기에서 최대 네 개의 watchpoint만 지원합니다. 다른 기기의 경우 더 적은 watchpoint를 지원할 수도 있습니다.

참고: 32비트 ARM ABI를 사용하여 앱을 디버깅할 때 watchpoint를 추가하거나 코드 내의 변수에 마우스를 가져가서 값을 조사하면 비정상 종료가 발생할 수 있습니다. 이 문제를 해결하려면 64비트 ARM, x86 또는 x86_64 바이너리를 사용하여 디버그합니다. 이 문제는 향후 Android 스튜디오 버전에서 해결될 예정입니다.

요구사항을 충족하면 다음과 같이 watchpoint를 추가할 수 있습니다.

  1. 중단점에서 앱이 정지된 동안 LLDB 세션 뷰의 Variables 창으로 이동합니다.
  2. 추적하려는 메모리 블록을 차지한 변수를 마우스 오른쪽 버튼으로 클릭하고 Add Watchpoint를 선택합니다.

    그림 9. 메모리의 변수에 watchpoint 추가
  3. 그림 9와 같이 watchpoint를 구성하는 대화상자가 나타납니다.

    다음 옵션으로 감시점을 구성합니다.

    • Enabled: 설정을 변경할 때까지 watchpoint를 무시하도록 Android 스튜디오에 지시하려면 이 옵션을 선택 해제합니다. Android 스튜디오는 나중에 watchpoint에 액세스할 수 있도록 watchpoint를 저장합니다.
    • Suspend: 기본적으로, Android 시스템은 watchpoint에 할당된 메모리 블록에 액세스할 때 앱 프로세스를 중단합니다. 이 동작을 원하지 않으면 이 옵션을 선택 해제합니다. 이를 통해 시스템에서 watchpoint와 상호작용할 때의 동작을 맞춤설정하는 데 사용할 수 있는 Log message to consoleRemove when hit과 같은 추가 옵션이 표시됩니다.
    • Access Type: 시스템이 변수에 할당한 메모리 블록을 대상으로 앱이 읽기 또는 쓰기를 시도할 때 앱이 watchpoint를 트리거할지 여부를 선택합니다. 읽기 또는 쓰기 시에 watchpoint를 트리거하려면 Any를 선택합니다.
  4. Done을 클릭합니다.

모든 watchpoint를 보고 watchpoint 설정을 구성하려면 Debug 창의 View Breakpoints 를 클릭합니다. 그림 10과 같은 Breakpoints 대화상자가 표시됩니다.

그림 10. 현재 watchpoint가 모두 나와 있고 각 watchpoint의 동작 설정이 포함된 Breakpoints 대화상자

watchpoint를 추가한 후 Debug 창에서 Resume Program 을 클릭하여 앱 프로세스를 계속합니다. 기본적으로, watchpoint를 설정했던 메모리 블록에 앱이 액세스하려고 시도하면 Android 시스템이 앱 프로세스를 중단하며 앱이 마지막으로 실행했던 코드 줄 옆에 watchpoint 아이콘 이 나타납니다(그림 11 참고).

그림 11. Android 스튜디오는 watchpoint를 트리거하기 직전에 앱이 실행하는 코드 줄을 나타냅니다.

리소스 값 표시 형식 보기 및 변경하기

디버그 모드에서 리소스 값을 확인하고 자바 코드 변수 또는 Kotlin 코드 변수의 다른 표시 형식을 선택할 수 있습니다. Variables 탭을 표시하고 프레임을 선택한 상태에서 다음 단계를 따르세요.

  1. Variables 목록에서 리소스 줄의 임의의 위치를 마우스 오른쪽 버튼으로 클릭하여 목록을 표시합니다.
  2. 목록에서 View as를 선택하고 사용할 형식을 선택합니다.

    사용 가능한 형식은 선택한 리소스의 데이터 유형에 따라 다릅니다. 다음 옵션 중 하나 이상이 표시될 수 있습니다.

    • Class: 클래스 정의를 표시합니다.
    • toString: 문자열 형식을 표시합니다.
    • Object: 객체(클래스의 인스턴스) 정의를 표시합니다.
    • Array: 배열 형식으로 표시합니다.
    • Timestamp: 날짜 및 시간을 yyyy-mm-dd hh:mm:ss 형식으로 표시합니다.
    • Auto: Android 스튜디오가 데이터 유형에 따라 최적의 형식을 선택합니다.
    • Binary: 0과 1을 사용하여 바이너리 값을 표시합니다.
    • MeasureSpec: 상위 요소로부터 선택한 하위 요소로 전달되는 값입니다. MeasureSpec을 참조하세요.
    • Hex: 16진수 값으로 표시합니다.
    • Primitive: 원시 데이터 유형을 사용하여 숫자 값으로 표시합니다.
    • Integer: Integer 유형의 숫자 값을 표시합니다.

맞춤 형식을 만들려면 다음 단계를 따르세요.

  1. 리소스 값을 마우스 오른쪽 버튼으로 클릭합니다.
  2. View as를 선택합니다.
  3. Create를 선택합니다.
  4. Java Data Type Renderers 대화상자가 표시됩니다. Java Data Type Renderers의 안내를 따릅니다.