개발 일지/기타

[Android] Hilt - java.lang.RuntimeException: Unable to instantiate application

interfacer_han 2025. 2. 1. 15:23

#1 문제 상황

#1-1 Hilt 도입

 

[Android] Dagger2 - Hilt로 마이그레이션

#1 Hilt 개요 Hilt를 사용한 종속 항목 삽입  |  Android Developers이 페이지는 Cloud Translation API를 통해 번역되었습니다. Hilt를 사용한 종속 항목 삽입 컬렉션을 사용해 정리하기 내 환경설정을 기준으

kenel.tistory.com

위 게시글에 기반해, 개발 중인 앱에 Hilt를 도입하고 있었다.

 

#1-2 Application 클래스

package com.example.nutri_capture_new.di

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class HiltApplication : Application()

"com.example.nutri_capture_new"는 내가 개발 중인 프로젝트 이름이다. 여기에 "di" 패키지를 만들고 HiltApplication.kt를 넣었다. Hilt는 Application 클래스를 요구하기 때문이다.

 

#1-3 에러 메시지

java.lang.RuntimeException: Unable to instantiate application com.example.nutri_capture_new.di.HiltApplication package com.example.nutri_capture_new: java.lang.ClassNotFoundException: Didn't find class "com.example.nutri_capture_new.di.HiltApplication" on path: DexPathList[[zip file "/data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/base.apk"],nativeLibraryDirectories=[/data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/lib/arm64, /data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/base.apk!/lib/arm64-v8a, /system/lib64, /system/system_ext/lib64]]
    at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1574)
    at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1503)
...

요약하면, HiltApplication 클래스를 찾을 수 없어 런타임 에러가 난다는 말이다.

 

전체 에러 메시지

더보기
더보기
java.lang.RuntimeException: Unable to instantiate application com.example.nutri_capture_new.di.HiltApplication package com.example.nutri_capture_new: java.lang.ClassNotFoundException: Didn't find class "com.example.nutri_capture_new.di.HiltApplication" on path: DexPathList[[zip file "/data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/base.apk"],nativeLibraryDirectories=[/data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/lib/arm64, /data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/base.apk!/lib/arm64-v8a, /system/lib64, /system/system_ext/lib64]]
    at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1574)
    at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1503)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7558)
    at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2400)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:226)
    at android.os.Looper.loop(Looper.java:313)
    at android.app.ActivityThread.main(ActivityThread.java:8762)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.nutri_capture_new.di.HiltApplication" on path: DexPathList[[zip file "/data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/base.apk"],nativeLibraryDirectories=[/data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/lib/arm64, /data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/base.apk!/lib/arm64-v8a, /system/lib64, /system/system_ext/lib64]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:637)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
    at android.app.AppComponentFactory.instantiateApplication(AppComponentFactory.java:76)
    at androidx.core.app.CoreComponentFactory.instantiateApplication(CoreComponentFactory.java:51)
    at android.app.Instrumentation.newApplication(Instrumentation.java:1232)
    at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1566)
    at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1503) 
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7558) 
    at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2400) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loopOnce(Looper.java:226) 
    at android.os.Looper.loop(Looper.java:313) 
    at android.app.ActivityThread.main(ActivityThread.java:8762) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067) 
    Suppressed: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/example/nutri_capture_new/di/Hilt_HiltApplication;
        at java.lang.VMClassLoader.findLoadedClass(Native Method)
        at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:1276)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:621)
        ... 16 more
    Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.nutri_capture_new.di.Hilt_HiltApplication" on path: DexPathList[[zip file "/data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/base.apk"],nativeLibraryDirectories=[/data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/lib/arm64, /data/app/~~V6g0-RtfopAougO3sWY7bA==/com.example.nutri_capture_new-blpUDwYEKGYG8Zyat-1NKA==/base.apk!/lib/arm64-v8a, /system/lib64, /system/system_ext/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:637)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
        ... 19 more

 

#2 원인 - kapt의 부재

plugins {
    ...
    // KSP (어노테이션 읽기용)
    id("com.google.devtools.ksp")
    // Hilt
    id("com.google.dagger.hilt.android")
}

android {
    ...
}

dependencies {

    ...

    // Hilt
    implementation("com.google.dagger:hilt-android:2.46")
    ksp("com.google.dagger:hilt-compiler:2.46")
}

KSP가 kapt의 완전한 상위호환이라고 생각한 것이 문제였다.

 

Hilt는 dagger2를 더 쉽게 사용하기 위해 만든 추상화 계층이다. 따라서 Hilt는 내부적으로는 dagger2라고 볼 수 있다. 그리고 dagger2는 기본적으로 kapt를 통해 어노테이션(@)을 처리한다. 이후에 KSP가 나왔는데, KSP는 kapt가 읽을 수 있는 어노테이션을 전부 커버하지 못한다. 즉, plungins { ... } 및 dependencies { ... }에 kapt 대신 KSP만 쓰면 읽지 못하는 어노테이션이 존재하게 된다. #1-2에 있는 어노테이션인 @HiltAndroidApp은 KSP로 읽을 수 없고 반드시 kapt로만 읽을 수 있는 어노테이션이기에, 안드로이드 런타임이 그 존재를 감지하지 못했던 것이다.

 

호환성과 성능을 둘 다 챙기려면 KSP와 kapt를 둘다 추가하면 된다 (#3 참조). 이러면 kapt로 처리해야만 하는 어노테이션은 kapt가 처리하고, 비교적 더 빠른 KSP가 처리할 수 있는 부분은 KSP로 처리하게 된다.

 

#3 해결

plugins {
    ...
    // KSP 및 kapt (어노테이션 읽기용)
    id("com.google.devtools.ksp")
    id("org.jetbrains.kotlin.kapt")
    // Hilt
    id("com.google.dagger.hilt.android")
}

android {
    ...
}

dependencies {

    ...

    // Hilt
    implementation("com.google.dagger:hilt-android:2.46")
    kapt("com.google.dagger:hilt-android-compiler:2.46")
    ksp("com.google.dagger:hilt-compiler:2.46")
}

 

#4 소스 코드

 

GitHub - Kanmanemone/nutri-capture-new

Contribute to Kanmanemone/nutri-capture-new development by creating an account on GitHub.

github.com

에러가 해결된 전체 소스 코드 (개발 중인 앱의 통짜 소스코드)

'개발 일지 > 기타' 카테고리의 다른 글

앞으로의 App 개발 일지 작성  (0) 2025.01.29