使用proGuard时如何保持java.lang.reflect?

时间:2018-06-27 10:38:29

标签: java android android-proguard

在我的应用程序中,我想使用此https://github.com/xmuSistone/AndroidPileLayout

当我的项目proguard告诉我可能有错误时,我想在项目中使用proguard

对于修订proguard,库开发人员说:

  

当您使用java.lang.reflect api时,proguard会出错,请   检查您自己的代码。

我的保护人规则:

#--------Glide--------
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
#--------Glide transformations--------
-dontwarn jp.co.cyberagent.android.gpuimage.**
#--------Retrofit--------
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-dontwarn com.squareup.retrofit2.**
-dontwarn retrofit2.Platform$Java8
#--------Gson--------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
#--------ButterKnife--------
# Retain generated class which implement Unbinder.
-keep public class * implements butterknife.Unbinder { public <init>(**, android.view.View); }
# Prevent obfuscation of types which use ButterKnife annotations since the simple name
# is used to reflectively look up the generated ViewBinding.
-keep class butterknife.*
-keepclasseswithmembernames class * { @butterknife.* <methods>; }
-keepclasseswithmembernames class * { @butterknife.* <fields>; }
#--------MyCustomViews--------
-keep class com.app.app.view.** { *; }
-keep class com.app.app.api.models.** { *; }
-keep class java.lang.reflect.** { *; }
-keepclassmembers public class java.lang.reflect.**

如何解决并保留java.lang.reflect

请帮助我

请帮助我

2 个答案:

答案 0 :(得分:0)

问题不是您需要将类保留在java.lang.reflect中,而是代码反射中的某处被用于在运行时加载,访问和潜在地修改类。

因为ProGuard和其他混淆器会重命名您的类,以使反向工程更加困难,所以在String中使用硬编码的类名将失败。例如,考虑以下代码:

com.acme.Acme acme = Class.forName("com.acme.Acme").newInstance();

现在考虑在com.acme.Acme上运行Proguard后,它可能已重命名为a.a.A。该代码将有效读取:

a.a.A acme = Class.forName("com.acme.Acme").newInstance();

这将在运行时导致ClassNotFoundException,这就是ProGuard会根据其配置发出警告或错误的原因。

解决方案是仔细调查您是否在自己的代码中使用反射,以及是否可以在其中使用反射,是否可以避免该反射,是否可以将其忽略,或者是否需要保留正在反射的类。在上。 在上面的示例中,您可以通过指定-keepnames com.acme.Acme来避免麻烦。如果使用反射来对类成员进行检查,则可能需要考虑-keep对整个类及其所有成员。

但是从本质上讲,混淆和反射并不能很好地融合在一起。

答案 1 :(得分:0)

获取运行时异常的原因可能会有所不同,具体取决于您实现的代码。 导致异常的原因之一可能是使用反射依赖代码中的字段/类/方法名称-ProGuard在混淆时会重命名您的类,因此为了使它们在混淆后可以访问,需要明确防止它们被混淆

-keep app.package.FancyClass { *; } 

如果是使混淆后的应用程序崩溃的库本身,那么我建议找到确切的位置,并明确保留发生异常的类所依赖的类。

最简单的情况是保留整个库:

-keep com.stone.pile.** { *; } 

,但是您经常可以将ProGuard配置为更具攻击性。不过,这是一个很好的起点。

我认为-keep java.lang.reflect.**规则在这里没有太大帮助。根本原因在于代码中依赖于类内部的东西,需要从混淆中排除它们。

找到易受攻击的代码,并尝试通过反射访问类/方法/内部对象。

编辑: 如果将指向异常抛出的位置粘贴到类文件中,将会很有帮助。异常消息也将加到上下文中。你能做到吗?