Proguard causing NoSuchMethodException - followup

橙三吉。 提交于 2019-12-11 09:13:00

问题


Following the suggestions from @AlexWein in this question and looking at ProGuard Troubleshooting, I have the following in a 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" constructor is:

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

Proguard is set up like so:

-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

But I am still getting a 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)

What am I missing?

Update

I have changed the Proguard lines to:

-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); }

And am still getting the error.

Looking at the mapping file, I think that I see what is causing the issue:

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

It looks like Proguard is keeping the reference to co.uk.MyApp.classes.Report_Holder, but is obfuscating it when referencing it as a child of co.uk.MyApp.DataActivity.

I've tried different ways of keeping co.uk.MyApp.DataActivity, trying to get it to stop obfuscating co.uk.MyApp.classes.Report_Holder, but can't get the syntax correct. Any suggestions?

Update 2

I have updated some code and the ProGuard config file as suggested by Eric Lafortune (btw, I am showing proper package/classnames now):

In 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 is:

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

Full ProGuard config is:

-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*

And the full error log is:

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)

回答1:


Your code accesses a method by means of reflection. The stack trace indicates that ProGuard has removed or renamed it. So, you should preserve it, with a line that is almost a direct copy of the headers of your code:

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

ProGuard recognizes the Class.forName construct and already preserves the class MyData. For good measure, you can make sure ProGuard doesn't remove the class Report_Holder (should the class happen to be unused, other than as an argument type):

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

Notes:

  • The ProGuard documentation explains the differences between the various -keep options. If you're not sure, just use -keep. Cfr. Usage > Overview of Keep Options.

  • You may have seen a warning in your console log that Report_Holder has to be specified with its fully qualified name.




回答2:


Solved!

I added these lines to the ProGuard config file:

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

I added SleepDataActivity because that is the class which holds the Async task which contacts pdfsleep.

I added SleepMainActivity because SleepDataActivity is, technically, a Fragment within a TabSwipe Activity and SleepMainActivity is the parent of those tabs.

'pdfsleep' is now mentioned in mapping.txt, and all works as intended.

I will accept Eric Lafortune's reply as the answer to this question, as his syntax for '-keepclassmembers' is not something I would have gotten to by myself, and also because I accepted the answer from AlexWien in a previous question which got me to this stage.

Thank you both, you have saved my launch date!




回答3:


One of your problems probably is that in the obfuscation rules you specify Report_Holder, but the method to exclude uses SleepReport_Holder.

I use this rule It is in ant proguard extension, but you can easily translate that to the other rule description system:

<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>

additionaly vor java > 1.5 use rule

-keepattributes Signature 

otherwise collections and generics will not work



来源:https://stackoverflow.com/questions/16703291/proguard-causing-nosuchmethodexception-followup

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!