【问题标题】:Android Proguard - ClassNotFoundExceptionAndroid Proguard - ClassNotFoundException
【发布时间】:2015-02-17 14:34:32
【问题描述】:

我为我的 android 应用启用了 proguard。我可以成功构建项目,但它在启动时因 classNotFoundException 而崩溃。它甚至找不到启动器活动。这是我的 proguard 规则文件

-libraryjars libs

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application

-keepnames class com.mypackage.** { *; } //someone suggested this but doesn't work

# We only want obfuscation
-keepattributes InnerClasses,Signature

# Sdk
-keep public interface com.zendesk.sdk.** { *; }
-keep public class com.zendesk.sdk.** { *; }

# Appcompat and support
-keep interface android.support.v7.** { *; }
-keep class android.support.v7.** { *; }
-keep interface android.support.v4.** { *; }
-keep class android.support.v4.** { *; }

# Gson
-keep interface com.google.gson.** { *; }
-keep class com.google.gson.** { *; }

# Retrofit
#-keep class com.google.inject.** { *; }
#-keep class org.apache.http.** { *; }
#-keep class org.apache.james.mime4j.** { *; }
#-keep class javax.inject.** { *; }
#-keep class retrofit.** { *; }
#-keep interface retrofit.** { *; }

# Retrofit
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**

-dontwarn rx.**
-dontwarn retrofit.**
-dontwarn okio.**
-keep class retrofit.** { *; }
-keepclasseswithmembers class * {
    @retrofit.http.* <methods>;
}

# Jackson
-keepattributes *Annotation*,EnclosingMethod,Signature
-keepnames class com.fasterxml.jackson.** { *; }
 -dontwarn com.fasterxml.jackson.databind.**
 -keep class org.codehaus.** { *; }
 -keepclassmembers public final enum org.codehaus.jackson.annotate.JsonAutoDetect$Visibility {
 public static final org.codehaus.jackson.annotate.JsonAutoDetect$Visibility *; }
-keep public class your.class.** {
  public void set*(***);
  public *** get*();
}

#Picasso
-dontwarn com.squareup.okhttp.**

#-dontwarn javax.management.**
#-dontwarn java.lang.management.**
#-dontwarn org.apache.log4j.**
#-dontwarn org.apache.commons.logging.**
#-dontwarn org.json.*
#-dontwarn org.apache.commons.codec.binary.Base64

#-keep class javax.** {* ; }
#-keep class org.** { *; }

-dontwarn org.mortbay.**
-dontwarn org.slf4j.**
-dontwarn org.apache.log4j.**
-dontwarn org.apache.commons.logging.**
-dontwarn org.apache.commons.codec.binary.** 

如果有帮助,这是我的 build.gradle 文件,但它不包含所有依赖项。我在 libs 文件夹中也有一些罐子。

apply plugin: 'com.android.application'
apply plugin: 'robolectric'
apply plugin: 'android'
apply plugin: 'newrelic'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "com.mypackage"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 54
        versionName "2.002"
        multiDexEnabled true
        testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
        resConfigs "en", "fr" , "ar"
    }
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets {
        androidTest {
            setRoot('src/test')
        }
    }

    dexOptions {
        javaMaxHeapSize "4g"
    }

    lintOptions {
        checkReleaseBuilds false
        // Or, if you prefer, you can continue to check for errors in release builds,
        // but continue the build even when errors are found:
        abortOnError false
    }

    repositories{
        maven { url 'https://zendesk.artifactoryonline.com/zendesk/repo' }
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        compile fileTree(dir: 'libs', include: '*.jar')
        compile 'com.android.support:appcompat-v7:21.+'
        compile 'com.github.chrisbanes.photoview:library:1.2.3'
        compile 'com.etsy.android.grid:library:1.0.5'
        compile 'com.facebook.android:facebook-android-sdk:3.21.1'
        compile 'com.google.android.gms:play-services-base:6.5.+'
        compile 'com.google.android.gms:play-services-wallet:6.5.+'
        compile 'com.google.android.gms:play-services-ads:6.5.+'
        compile 'com.google.android.gms:play-services-maps:6.5.+'
        compile 'com.google.android.gms:play-services-drive:6.5.+'
        compile 'com.google.android.gms:play-services-appindexing:6.5.+'
        compile 'com.google.android.gms:play-services-location:6.5.+'
        compile 'com.google.android.gms:play-services-identity:6.5.+'
        compile 'com.google.android.gms:play-services-plus:6.5.+'
        compile 'com.android.support:multidex:1.0.+'
        compile project(':Adjust')
        compile project(':aFileChooser-cbccac1d1cb74a6d57d25c5ded61e4bf4fc40c91')
        compile 'com.parse.bolts:bolts-android:1.+'
        compile 'com.squareup.picasso:picasso:2.4.0'
        compile 'com.android.support:recyclerview-v7:+'
        compile (group: 'com.zendesk', name: 'sdk', version: '1.0.0.1'){
            //    exclude group:'picasso'
        }
        compile 'com.android.support:recyclerview-v7:+'
        compile 'com.newrelic.agent.android:android-agent:4.+'
        compile 'com.fasterxml.jackson.core:jackson-databind:2.4.2'
        compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.2'
        compile 'com.fasterxml.jackson.core:jackson-core:2.4.2'


        /*compile ('oauth.signpost:signpost-commonshttp4:1.2.1.2') {
            exclude module: 'commons-logging'
            exclude module: 'httpcore'
            exclude module: 'httpclient'
        }
        compile ('oauth.signpost:signpost-core:1.2.1.2') {
            exclude module: 'commons-codec'
        }*/

        androidTestCompile 'org.robolectric:robolectric:2.4'
        androidTestCompile('junit:junit:4.12')
        androidTestCompile('org.mockito:mockito-core:1.10.19')

    }

    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/ASL2.0'
        exclude 'LICENSE.txt'
    }
}



robolectric {
    include '**/*Test.class'
}

这是完整的堆栈跟踪:

02-17 19:01:09.752: E/AndroidRuntime(2079): FATAL EXCEPTION: main
02-17 19:01:09.752: E/AndroidRuntime(2079): Process: com.mypackage, PID: 2079
02-17 19:01:09.752: E/AndroidRuntime(2079): java.lang.NoClassDefFoundError: Failed resolution of: Lcom/mypackage/activities/MainActivity;
02-17 19:01:09.752: E/AndroidRuntime(2079):     at cmypackage.application.ApplicationContextProvider.onCreate(Unknown Source)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1011)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4518)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at android.app.ActivityThread.access$1500(ActivityThread.java:144)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1339)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at android.os.Handler.dispatchMessage(Handler.java:102)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at android.os.Looper.loop(Looper.java:135)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at android.app.ActivityThread.main(ActivityThread.java:5221)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at java.lang.reflect.Method.invoke(Native Method)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at java.lang.reflect.Method.invoke(Method.java:372)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
02-17 19:01:09.752: E/AndroidRuntime(2079): Caused by: java.lang.ClassNotFoundException: Didn't find class "mypackage.activities.MainActivity" on path: DexPathList[[zip file "/data/app/mypackage-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
02-17 19:01:09.752: E/AndroidRuntime(2079):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
02-17 19:01:09.752: E/AndroidRuntime(2079):     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
02-17 19:01:09.752: E/AndroidRuntime(2079):     ... 12 more
02-17 19:01:09.752: E/AndroidRuntime(2079):     Suppressed: java.lang.NoClassDefFoundError: mypackage.activities.MainActivity
02-17 19:01:09.752: E/AndroidRuntime(2079):         at dalvik.system.DexFile.defineClassNative(Native Method)
02-17 19:01:09.752: E/AndroidRuntime(2079):         at dalvik.system.DexFile.defineClass(DexFile.java:226)
02-17 19:01:09.752: E/AndroidRuntime(2079):         at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:219)
02-17 19:01:09.752: E/AndroidRuntime(2079):         at dalvik.system.DexPathList.findClass(DexPathList.java:321)
02-17 19:01:09.752: E/AndroidRuntime(2079):         at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54)
02-17 19:01:09.752: E/AndroidRuntime(2079):         ... 14 more
02-17 19:01:09.752: E/AndroidRuntime(2079):     Suppressed: java.lang.ClassNotFoundException: mypackage.MainActivity
02-17 19:01:09.752: E/AndroidRuntime(2079):         at java.lang.Class.classForName(Native Method)
02-17 19:01:09.752: E/AndroidRuntime(2079):         at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
02-17 19:01:09.752: E/AndroidRuntime(2079):         at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
02-17 19:01:09.752: E/AndroidRuntime(2079):         at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
02-17 19:01:09.752: E/AndroidRuntime(2079):         ... 13 more
02-17 19:01:09.752: E/AndroidRuntime(2079):     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

编辑:以下是堆栈跟踪中缺少的部分。

02-17 19:01:09.749: I/MultiDex(2079): VM with version 2.1.0 has multidex support
02-17 19:01:09.749: I/MultiDex(2079): install
02-17 19:01:09.749: I/MultiDex(2079): VM has multidex support, MultiDex support library is disabled.
02-17 19:01:09.750: I/art(2079): Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.app.FragmentActivity>
02-17 19:01:09.750: I/art(2079): Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.app.FragmentActivity>
02-17 19:01:09.751: I/art(2079): Rejecting re-init on previously-failed class java.lang.Class<mypackage.activities.MainActivity>
02-17 19:01:09.751: I/art(2079): Rejecting re-init on previously-failed class java.lang.Class<mypackage.activities.MainActivity>
02-17 19:01:09.751: D/AndroidRuntime(2079): Shutting down VM
02-17 19:01:09.751: D/AndroidRuntime(2079): --------- beginning of crash

【问题讨论】:

  • 请从 logcat 添加完整的堆栈跟踪。
  • @Trinimon 发布了堆栈跟踪
  • 我想如果你禁用 proguard 一切正常吧?
  • 完全正确。我在堆栈跟踪中遗漏了一些东西。我正在编辑问题以添加它。它可能会给你一个线索
  • @Trinimon 编辑了我的问题。请看一看。谢谢

标签: android proguard obfuscation android-proguard


【解决方案1】:

您还需要确保在此处添加 New Relic proguard 例外:https://docs.newrelic.com/docs/mobile-monitoring/mobile-monitoring-installation/android/installing-android-apps-gradle-android-studio#proguard

-keep class com.newrelic.** { *; }
-dontwarn com.newrelic.**
-keepattributes Exceptions, Signature, InnerClasses

【讨论】:

  • 非常感谢。它工作:) 但在调试构建中尝试它时。我每次都必须构建项目,因为执行失败并显示:app:retraceDebugMainDexClassList FAILED Error:Execution failed for task ':app:retraceDebugMainDexClassList'。 > 无法读取映射文件。对此有什么想法吗?
  • 使用minifyEnabled true 进行调试构建并不能真正为您带来很多好处。将其设置为 false 以进行调试构建会消除错误吗?
  • 我只是想在调试版本上测试它。现在很好。但无法使用 proguard-android-optimize.txt 构建。它可以与 proguard-android.txt 一起使用
  • 好吧,在您的 build.gradle 中,您已经为发布和调试构建类型指定了 proguard-android.txt 而不是 proguard-android-optimize.txt。这可能就是为什么它不起作用的原因。
  • 我的意思是当我将上面的内容更改为optimize.txt时,构建失败。
【解决方案2】:

删除与活动相关的混淆规则以及所有与支持库相关的混淆规则。Android Studio 默认具有这些模板。您可以通过在您的 gradle 中添加此规则来启用它们

buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt')
        }
    }

另外请编辑 Jackson 处理器的规则

-keep public class your.class.** {
  public void set*(***);
  public *** get*();
}

在您的类中。** 是您为解析响应而创建的 POJO(getter/setter) 类

【讨论】:

  • 我删除了规则。并编辑了杰克逊处理器,但仍然是同样的问题。我将引用杰克逊库的类添加到上述语句中,但没有帮助
  • 还有关于 buildType 的配置。我已经在这样做了。我已将所有规则添加到 proguard-android.txt 文件中
  • 那是对的,那你为什么要专门将android规则添加到你的规则集中,删除它们
  • 是的,我做到了。删除了所有与 android 相关的规则。但仍然遇到同样的问题。我担心的是 logcat 中的这一行:VM has multidex support,MultiDex support library is disabled。我认为这是一个多索引问题。在启用 multidex 之前,我有相同的 classNotfound 异常。正确启用multidex后,我摆脱了它,但现在启用proguard后,我遇到了同样的问题
【解决方案3】:

我知道这是一篇相当老的帖子,但我想强调以下内容,如果它对未来的人有所帮助。

ClassNotFoundException 是对使用反射访问的类应用名称混淆引起的异常。例如,如果 ProGuard 重命名类 MyClass,在代码中访问它:Class.forName("MyClass");,如果字符串仍然引用 MyClass,则会抛出 ClassNotFoundException

这是我们需要添加 -keep 选项的地方,以便 ProGuard 不会重命名该类;

-keep class com.example.MyClass

当使用广泛的-keep 选项(以.** { *; } 结尾)时,您将指示 ProGuard 不要缩小、优化或混淆通配符之前提到的包名称的所有类和类成员。这最终会导致一个优化不佳的项目。因此,最好将此类-keep 选项缩小到仅针对缺失的类。在 OP 的示例中,抛出以下错误:

Caused by: java.lang.ClassNotFoundException: Didn't find class "mypackage.activities.MainActivity"

为缺少的类添加-keep 选项(如下所示)将解决此特定问题;

-keep class mypackage.activities.MainActivity

如果您将-addconfigurationdebugging 添加到配置文件中,ProGuard 可以帮助您设置缩小的-keep 选项,有关此功能的更多详细信息记录在ProGuard 手册here 中。

最近发布了ProGuard Playground,您可以快速看到广泛的-keep 选项与缩小选项的效果。这里的一个很好的好处是您不需要不断(重新)构建项目。

【讨论】:

    猜你喜欢
    • 2015-04-19
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2011-03-06
    • 2011-06-20
    • 2013-07-20
    • 1970-01-01
    相关资源
    最近更新 更多