如何修复Proguard警告“找不到引用的方法”,针对现有类java.lang.Object中的方法'clone'和'finalize'?

17

我尝试压缩一个使用ical4j.jar的Android应用程序。

当我使用gradle proguardDebug构建apk时,使用proguard会得到以下警告:

  • 警告:net.fortuna.ical4j.model.CalendarFactory:在库类java.lang.Object中找不到引用方法void finalize()。
    • finalize()有6个类似的警告
  • 警告:net.fortuna.ical4j.model.CalendarFactory:在库类java.lang.Object中找不到引用方法java.lang.Object clone()。
    • clone()有6个类似的警告

我已经验证过android-7支持finalize()clone():“... \ Android ... \ sdk \ platforms \ android-7 \ android.jar”在类java.lang.Object中具有方法finalize()clone()

你有任何想法如何解决这个问题吗?

注意:这不是其他“proguard找不到引用方法”的重复问题,因为在我的特定情况下,我认为缺少的方法应该在那里。

我正在使用

  • proguard-4.11
  • gradle-1.11
    • Groovy: 1.8.6
    • Ant: Apache Ant(TM) version 1.9.2 compiled on July 8 2013
    • Ivy: 2.2.0
    • JVM: 1.7.0_25 (Oracle Corporation 23.25-b01)
    • OS: Windows 7 6.1 amd64
  • ical4j.jar 1.0.5

这是可能需要修复的proguard配置proguard-rules.txt

#  proguard-rules.txt
## ical4j also contains groovy code which is not used in android 
-dontwarn groovy.**
-dontwarn org.codehaus.groovy.**
-dontwarn org.apache.commons.logging.**
-dontwarn sun.misc.Perf

-dontnote com.google.vending.**
-dontnote com.android.vending.licensing.**

这是我的build.gradle文件。
    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:0.9.+'
            classpath 'net.sf.proguard:proguard-gradle:4.11'
        }
    }

    allprojects {
        repositories {
            mavenCentral()
        }
    }

    apply plugin: 'android'

    configurations {
        compile.exclude group: 'commons-logging' // referenced in some portable lib. use androids internal instead
    }

    android {
        compileSdkVersion 19
        buildToolsVersion '19.0.3'

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

        defaultConfig {
            minSdkVersion 7
            targetSdkVersion 19
        }

        buildTypes {
            release {
                runProguard false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            }

            // used for testing. remove if it works as expected
            debug {
                runProguard true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            }
        }
    }

    dependencies {
        compile 'org.mnode.ical4j:ical4j:1.0.5'
        compile 'backport-util-concurrent:backport-util-concurrent:3.1'
        compile 'commons-codec:commons-codec:1.8'
        compile 'commons-lang:commons-lang:2.6'
    }

[更新于2014年12月20日]

我已经在下面的答案中添加了我的工作配置。

注意:对于当前的Android Studio 1.0(android.buildToolsVersion >= '20'),你必须用minifyEnabled替换runProguard

例如:

    android {
        buildTypes {
            release {
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            }
    }
3个回答

19

net.fortuna.ical4j.model.CalendarFactory 继承自 groovy.util.AbstractFactory,后者又继承自 java.lang.Object。然而,你的输入中缺少了中间的那个类(通过 -dontwarn 抑制了相应的警告)。由于类层次结构的一部分缺失,ProGuard 没有意识到 CalendarFactory 可能会访问受保护的方法 clonefinalize,因此会打印出这些警告信息。

由于你的代码可能根本不使用该类,你可以抑制这些警告:

-dontwarn net.fortuna.ical4j.model.CalendarFactory

或者对于覆盖所有类似的类:

-dontwarn net.fortuna.ical4j.model.**

对于此问题,您不应添加任何-keep选项; Android SDK已经为您指定了与Android相关的基本-keep选项。


我按照建议移除了 -keep class net.fortuna.ical4j.model.** { *; },这使得 APK 额外减少了 60kb。幸运的是,我的 Android 应用程序不使用任何依赖 Groovy 的类。我更新了自己的答案,提供了最终解决方案。 - k3b

2
这是我的ProGuard配置文件。试着复制粘贴它。
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose    

# standard, except v4.app.Fragment, its required when app uses Fragments

-keep public class * extends android.app.Activity
-keep public class * extends android.support.v7.app.ActionBarActivity
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider

-keepclasseswithmembers class * {
    native <methods>;
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

-keepclassmembers class * extends android.app.Activity { 
       public void *(android.view.View); 
}

然后添加你的代码,如下所示: 在使用时

-dontwarn groovy.**

另外添加

-keep class groovy.** { *; }

请对所有外部库执行此操作。


1
谢谢回答。我尝试添加您的配置,但结果仍然是相同的错误。大多数针对Android的规则,比如“-keep public class * extends android.app.Activity”,应该来自于“Android/.../tools/proguard/proguard-android(-optimize).txt”。 - k3b
你尝试过使用-keep class吗?我知道我的文件正在使用所有的Android特定规则。你可以尝试通过从project.properties文件中删除${sdk.dir}/tools/proguard/proguard-android.txt来关闭这个系统规则(当你使用eclipse时)。 - Dawid C
我没有在Groovy部分使用keep,因为我不想保留该库的Groovy部分。然而,在我的当前解决方法中,我正在使用keep。尽管这不是解决方案,但它对我帮助很大,所以我将这个答案从-1点赞到0。 - k3b

-1

[更新 2014-05-30 重新组织了这段文字]

感谢 @EricLafortune 的答案,帮助我理解和解决了问题。

对于其他想要压缩 Android ical4j 应用程序的人,这是我的工作解决方案:

所有带有 in library class java.lang.Object 的类 - 问题来自命名空间。

 net.fortuna.ical4j.model.**

所以我将这些行添加到proguard-rules.txt

###################
# Get rid of #can't find referenced method in library class java.lang.Object# warnings for clone() and finalize()
# for details see https://dev59.com/z2Ag5IYBdhLWcg3wM4db
-dontwarn net.fortuna.ical4j.model.**

###############
# I use proguard only to remove unused stuff and to keep the app small.
# I donot want to obfuscate (rename packages, classes, methods, ...) since this is open source
-keepnames class ** { *; }
-keepnames interface ** { *; }
-keepnames enum ** { *; }

统计数据:

  • 未混淆:932个类;APK文件大小911KB。
  • 已混淆:365个类;APK文件大小505KB。

4
如果你不需要或不想混淆代码,有一个选项可以使用:"-dontobfuscate"。 - Pelpotronic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接