如何修复类 java.lang.Object 的现有方法“clone”和“finalize”的 proguard 警告“找不到引用的方法”

Posted

技术标签:

【中文标题】如何修复类 java.lang.Object 的现有方法“clone”和“finalize”的 proguard 警告“找不到引用的方法”【英文标题】:how to fix proguard warning 'can't find referenced method' for existing methods 'clone' and 'finalize' of class java.lang.Object 【发布时间】:2014-07-15 23:44:11 【问题描述】:

我尝试压缩一个消耗 ical4j.jarandroid 应用程序。

当我使用 gradle proguardDebug 构建带有 proguard 的 apk 时,我得到了

警告: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" 有方法 finalize()clone()在课堂上java.lang.Object

你知道如何解决这个问题吗?

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

我正在使用

proguard-4.11 与 gradle-1.11 Groovy:1.8.6 Ant:2013 年 7 月 8 日编译的 Apache Ant(TM) 版本 1.9.2 常春藤:2.2.0 JVM:1.7.0_25(甲骨文公司 23.25-b01) 操作系统: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'),您必须替换 runProguardminifyEnabled

例子

    android 
        buildTypes 
            release 
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            
    

【问题讨论】:

【参考方案1】:

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 额外减少了 60 kb。不幸的是,我的 android 应用程序不使用任何 groovy 相关类。我用最终解决方案更新了自己的答案【参考方案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.**  *; 

为所有外部库执行此操作。

【讨论】:

感谢您的回答。我试图添加你的配置,但结果是同样的错误。大多数android特定规则,如-keep public class * extends android.app.Activity 应该来自Android/.../tools/proguard/proguard-android(-optimize).txt 你试过使用 -keep class 吗?我知道我的文件正在使用所有 android 特定规则。您可以尝试通过从 project.properties 文件中删除 $sdk.dir/tools/proguard/proguard-android.txt 来关闭此系统规则(即当您使用 eclipse 时) 我没有将 keep 用于 groovy 部分,因为我不想保留 lib 的 groovy 部分。但是,我在当前的解决方法中使用了 keep 。我将这个答案从 -1 投票到 0,因为它对我有很大帮助,尽管它不是解决方案【参考方案3】:

[更新 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 http://***.com/questions/23883028/how-to-fix-proguard-warning-cant-find-referenced-method-for-existing-methods
-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

【讨论】:

如果您不需要/不想混淆,可以使用一个选项:“-dontobfuscate”。

以上是关于如何修复类 java.lang.Object 的现有方法“clone”和“finalize”的 proguard 警告“找不到引用的方法”的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.Object

java.lang.Object

maven找不到java.lang.object的类文件

java.lang.Object 的受保护方法如何免受子类的影响?

Java超类-java.lang.object

为啥 Java 中的每个对象都隐式扩展 java.lang.Object 类?