【问题标题】:Proguard causing NoSuchMethodException - followupProguard 导致 NoSuchMethodException - 跟进
【发布时间】:2013-05-25 04:12:15
【问题描述】:

按照@AlexWein 在this question 中的建议并查看ProGuard Troubleshooting,我在SherlockFragment 中有以下内容:

Class<?> c = Class.forName("co.uk.MyApp.pdf.MyData");
Method main = c.getDeclaredMethod("pdfsleep", Report_Holder.class);
Report_Holder paramsh = null;
paramsh = SRH;
main.invoke(null, (Object)paramsh);

“co.uk.MyApp.pdf.Data”构造函数是:

public class MyData {
public static void pdfsleep(Report_Holder args) {
...
}
}

Proguard 是这样设置的:

-keepnames class co.uk.MyApp.classes.Report_Holder
-keepclassmembers class co.uk.MyApp.pdf.Data { public static void   pdfsleep(Report_Holder); }
-keepnames class co.uk.MyApp.DataActivity

但我仍然收到 NoSuchMethodException:

05/23/13 12:14:28 GMT+01:00 ERROR  AsyncTask #2 - java.lang.NoSuchMethodException: pdfsleep [class co.uk.MyApp.classes.Report_Holder]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
at java.lang.Class.getDeclaredMethod(Class.java:685)
at co.uk.MyApp.fy.a(Unknown Source)
at co.uk.MyApp.fy.doInBackground(Unknown Source)
at android.os.AsyncTask$2.call(AsyncTask.java:264)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)

我错过了什么?

更新

我已将 Proguard 行更改为:

-keepattributes Signature
-keepnames class co.uk.MyApp.classes.Report_Holder
-keepclasseswithmembers class co.uk.MyApp.DataActivity 
-keepclasseswithmembers class co.uk.MyApp.pdf.Data { void pdfsleep(Report_Holder); }

我仍然收到错误。

查看映射文件,我想我知道是什么导致了问题:

co.uk.MyApp.classes.Report_Holder -> co.uk.MyApp.classes.Report_Holder:

co.uk.MyApp.DataActivity -> co.uk.MyApp.DataActivity:
java.util.ArrayList arrDataItems -> a
co.uk.MyApp.classes.Report_Holder SRH -> b

看起来 Proguard 保留了对 co.uk.MyApp.classes.Report_Holder 的引用,但在将其作为 co.uk.MyApp.DataActivity 的子项引用时对其进行了混淆。

我尝试了不同的方法来保留 co.uk.MyApp.DataActivity,试图让它停止混淆 co.uk.MyApp.classes.Report_Holder,但无法正确获取语法。有什么建议吗?

更新 2

我已经按照 Eric Lafortune 的建议更新了一些代码和 ProGuard 配置文件(顺便说一句,我现在正在显示正确的包/类名):

在 co.uk.FibroApp.SleepDataActivity

Class<?> c = Class.forName("co.uk.FibroApp.pdf.SleepData");
Method main = c.getDeclaredMethod("pdfsleep", co.uk.FibroApp.classes.SleepReport_Holder.class);

SleepReport_Holder paramsh = SRH;

co.uk.FibroApp.pdf.SleepData 是:

public class SleepData {
public static void pdfsleep(co.uk.FibroApp.classes.SleepReport_Holder args) {
...
}
}

完整的 ProGuard 配置是:

-keepattributes Signature

-keep class co.uk.FibroApp.classes.SleepReport_Holder
-keep class co.uk.FibroApp.pdf.SleepData
-keepclassmembers class co.uk.FibroApp.pdf.SleepData {
    public static void pdfsleep(co.uk.FibroApp.classes.SleepReport_Holder);
}

# do not obfuscate the classes from droidtext but shrink them
-keep,allowshrinking class harmony.java.awt.** { *; }
-keep,allowshrinking class org.apache.harmony.** { *; }
-keep,allowshrinking class org.bouncycastle.** { *; }

-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class com.actionbarsherlock.** { *; }
-keep interface com.actionbarsherlock.** { *; }

-keepattributes *Annotation*

完整的错误日志是:

05/24/13 08:25:52 WEST ERROR  AsyncTask #2 - java.lang.NoSuchMethodException: sleeppdf [class co.uk.FibroApp.classes.SleepReport_Holder]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
at java.lang.Class.getDeclaredMethod(Class.java:685)
at co.uk.FibroApp.fy.a(Unknown Source)
at co.uk.FibroApp.fy.doInBackground(Unknown Source)
at android.os.AsyncTask$2.call(AsyncTask.java:264)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)

【问题讨论】:

  • 这行还是错的:SleepReport_Holder paramsh = null;
  • 抱歉,我是从错误的文件中复制过来的——现在已经更新了
  • 地图文件中的pdfsleep在哪里?
  • 你的代码在不被混淆时是否有效?
  • 嗨。 pdfsleep 根本没有出现在 mapping.txt 中。

标签: android proguard


【解决方案1】:

解决了!

我将这些行添加到 ProGuard 配置文件中:

-keep class co.uk.FibroApp.pdf.SleepDataActivity
-keep class co.uk.FibroApp.pdf.SleepMainActivity

我添加了 SleepDataActivity,因为它是包含与 pdfsleep 联系的异步任务的类。

我添加了 SleepMainActivity,因为从技术上讲,SleepDataActivity 是 TabSwipe Activity 中的一个片段,而 SleepMainActivity 是这些选项卡的父级。

'pdfsleep' 现在在 mapping.txt 中被提及,并且一切正常。

我会接受 Eric Lafortune 的回复作为对这个问题的回答,因为他的“-keepclassmembers”语法不是我自己能得到的,而且我在上一个问题中接受了 AlexWien 的回答,得到了我到了这个阶段。

谢谢你们,你们保存了我的发布日期!

【讨论】:

    【解决方案2】:

    您的代码通过反射访问方法。堆栈跟踪表明 ProGuard 已将其删除或重命名。因此,您应该保留它,其中一行几乎是代码标题的直接副本:

    -keepclassmembers class co.uk.MyApp.pdf.MyData {
        public static void pdfsleep(co.uk.MyApp.classes.Report_Holder);
    }
    

    ProGuard 识别 Class.forName 结构并且已经保留了 MyData 类。为了更好地衡量,您可以确保 ProGuard 不会删除类 Report_Holder(如果该类碰巧未使用,而不是作为参数类型):

    -keep,allowobfuscation class co.uk.MyApp.classes.Report_Holder
    

    注意事项:

    • ProGuard 文档解释了各种 -keep 选项之间的差异。如果您不确定,只需使用 -keep。参照。用法 > Overview of Keep Options.

    • 您可能在控制台日志中看到一条警告,指出必须使用其完全限定名称指定 Report_Holder。

    【讨论】:

    • 我非常希望这是解决方案,但事实并非如此。我在我的问题中添加了“更新 2”,以详细说明我做了什么以及发生了什么。
    【解决方案3】:

    您的一个问题可能是在混淆规则中您指定Report_Holder, 但排除方法使用SleepReport_Holder

    我使用这条规则 它在 ant proguard 扩展中,但您可以轻松地将其转换为其他规则描述系统:

    <keepclasseswithmembers name="co.uk.MyApp.pdf.MyData" access="public">
    <method access="public static" type="void" name="pdfsleep" parameters="co.uk.MyApp.classes.SleepReport_Holder" />
    </keepclasseswithmembers>
    

    另外 vor java > 1.5 使用规则

    -keepattributes Signature 
    

    否则集合和泛型将不起作用

    【讨论】:

    • 对不起,这是一个错字,我已经修正了。我想我可能已经确定了导致错误的原因,但是在修复它的语法上遇到了问题。我已经更新了我上面的问题。
    猜你喜欢
    • 1970-01-01
    • 2020-09-06
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    • 2017-05-16
    • 2019-01-09
    • 2018-01-23
    • 1970-01-01
    相关资源
    最近更新 更多