我在我的Android应用程序中使用XStream对xml进行反序列化,现在我正在努力添加Proguard(混淆器)。
这是我遇到的运行时异常(完整:pastebin):
WARN/System.err(6209): net.lp.collectionista.util.a.g: XStream could not parse the response
WARN/System.err(6209): at net.lp.collectionista.a.s.a(Collectionista:215)
...
WARN/System.err(6209): Caused by: com.thoughtworks.xstream.converters.ConversionException: id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk] : id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk]
WARN/System.err(6209): ---- Debugging information ----
WARN/System.err(6209): message : id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk]
WARN/System.err(6209): cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
WARN/System.err(6209): cause-message : id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk]
WARN/System.err(6209): class : net.lp.collectionista.jaxb.googlebooks.search.Feed
WARN/System.err(6209): required-type : java.lang.Object
WARN/System.err(6209): path : /feed/entry/id
WARN/System.err(6209): line number : 1
WARN/System.err(6209): -------------------------------
WARN/System.err(6209): at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(Collectionista:89)
...
WARN/System.err(6209): at com.thoughtworks.xstream.XStream.fromXML(Collectionista:861)
...
WARN/System.err(6209): Caused by: com.thoughtworks.xstream.mapper.CannotResolveClassException: id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk]
WARN/System.err(6209): at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(Collectionista:68)
...
毋庸置疑,如果没有Proguard,这样可以正常工作。我在这里使用缩小,优化和混淆,虽然我在任何XStream类上都禁用了它,以及任何代表xml字段模型的类:
-keep class net.lp.collectionista.jaxb.** { *; }
-keep class com.thoughtworks.xstream.** { *; }
我可以从混淆的jar以及来自mapping.txt(对于方法)确认,提到的任何类都存在并且没有被混淆,因此未触及AFAICT。我也保留注释。
这个例外很清楚。我有:
xstream.omitField(Feed.class, "id");
等。似乎omitField()调用不再起作用,它开始寻找一个“id”模型类,因为Proguard。这是我陷入困境的地方,即使在深入了解XStream代码之后。模糊的最终结果中的整个omitField调用似乎完好无损,那么还有什么可以在这里进一步破解?它也应该不是“Feed.class”,因为它仍然存在。我错过了什么?调试的下一步是什么?
编辑:我注意到我的混淆jar中xstream类的类文件略小于原始类,即使使用-dontoptimize也是如此。什么还在被丢弃?
EDIT2:我开始认为它与缺少类似于以下内容的dex警告有关:
[apply] warning: Ignoring InnerClasses attribute for an anonymous inner class
[apply] (com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$1) that doesn't come with an
[apply] associated EnclosingMethod attribute. This class was probably produced by a
[apply] compiler that did not target the modern .class file format. The recommended
[apply] solution is to recompile the class from source, using an up-to-date compiler
[apply] and without specifying any "-target" type options. The consequence of ignoring
[apply] this warning is that reflective operations on this class will incorrectly
[apply] indicate that it is *not* an inner class.
......或许不是......
EDIT3:最后,尽管遇到了许多其他错误和问题,例如the SimException bug,我仍然能够在一些有限的情况下使用它。这样我就可以在混淆步骤中找到它。也就是说,至少,如果我添加“-dontobfuscate”,问题就会消失。这不是我第一次玩这个,所以它必须是其他问题或更窄配置的解决方法,以缓解这个问题。所以我再次问:当我已经使用“-keep”保护了xstream的主要部分和我的模型类的混淆时,那还有什么可以造成这种混乱?
如果您需要更多信息,请与我们联系。
答案 0 :(得分:3)
正如我所说,如果你-dontobfuscate
,问题就会消失,但我们假设你不想这样做。
解决方案是保留更多属性:
-keepattributes EnclosingMethod, InnerClasses
-keepattributes *Annotation*
-keepattributes Signature
一旦你开始工作,你可以缩小XStream代码的哪些部分。我有:
-keep class com.thoughtworks.xstream.converters.extended.SubjectConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.ThrowableConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.StackTraceElementConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.CurrencyConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.RegexPatternConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.CharsetConverter { *; }
-keep class com.thoughtworks.xstream.annotations.** { *; }
您还可以禁用许多与XStream相关的警告。
有关详细信息,请在此处找到我的版本控制项目文件:
答案 1 :(得分:2)
我似乎是ProGuard和XStream for Android存在问题的众多人之一。经过一些试验和研究,以下是对我有用的 - 一个完整的配置文件和一些解释性的评论,为什么我做了我做的。请注意,我的优先考虑是混淆,但我并不关心优化或缩小。
你需要记住,使用这个配置(保留库的公共成员 - 见下文),你需要使用XStream用来创建XML的类的“公共”成员,因为XStream将使用成员XML标签的名称 - 您不希望将XML标签更改为“a”,“b”或“c”:)祝您好运!
###########################################################
#
# FLAGS
#
###########################################################
# Not sure if I need this one, but seems to do no harm
-keepdirectories
# I needed NOT to optimize for SWT or XStream would not work, but for Android I do not seem to need to do that.
# However, if I try to shrink, XStream fails for Android. This different behaviour is a bit odd and black magic.
# However, I do not much care about optimization or size, and stability is more important for me, so let's
# neither optimize nor shrink (and shrinking saved us only about 1.5% of the size anyway).
#
# Note: this was not all that was necessary to make XStream run for Android - see other comments
# (search for XStream)
-dontshrink
-dontoptimize
# The following was configured for Android by default but now it does not make sense because I do not optmize, so disable just in case.
# -optimizationpasses 5
# Not sure if I need this one, but seems to do no harm.
-keeppackagenames
# This was configured for Android by default and it can only help.
-dontusemixedcaseclassnames
# This was configured for Android by default, and it is the default option as of ProGuard 4.5 anyway.
-dontskipnonpubliclibraryclasses
# ProGuard documentation says:
# For Java 6, preverification is optional, but as of Java 7, it is required.
# Only when eventually targeting Android, it is not necessary, so you can then
# switch it off to reduce the processing time a bit.
-dontpreverify
# Specifies to write out some more information during processing. If the
# program terminates with an exception, this option will print out the
# entire stack trace, instead of just the exception message.
-verbose
# Since I have turned off optmization, it makes no sense to have the following
# option enabled.
#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# The followig was necessary or it would not build, as it otherwise wants a totally clean build first.
-ignorewarnings
###########################################################
#
# -keep SPECIFICATIONS
#
###########################################################
# I tried adding those to fix the XStream problem, but in the end fixed it differently (see other comments).
#-keepattributes EnclosingMethod, InnerClasses
#-keepattributes *Annotation*
#-keepattributes Signature
# The following was configured for Android by default.
-keep public class * extends android.app.Activity
-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
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
# I tried adding those to fix the XStream problem, but in the end fixed it differently (see other comments).
# However, it might still be a good idea to stay away from thoughtworks for stability's sake.
# (Not sure if the second keep does not include the first one.)
-keep class com.thoughtworks.xstream.*
-keep class com.thoughtworks.xstream.* {
public protected <methods>;
public protected <fields>;
}
# The following plus not-shrinking seems necessary to make XStream run for Android.
# But again, as for SWT, I did not need to exclude all, public and protected methods and fields:
# just doing the public fields was enough.
# public protected <methods>;
# public protected <fields>;
-keep public class * {
public <fields>;
}
# This was configured for Android by default - and very necessary it is too.
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# I put it in because we might need this one in the future.
# This was default for the Windows installation of ProGuard, which said:
# Also keep - Database drivers. Keep all implementations of java.sql.Driver.
-keep class * extends java.sql.Driver
# This was configured for Android by default.
-keepclasseswithmembernames class * {
native <methods>;
}
# This was configured for Android by default.
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
# This was configured for Android by default.
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
# This was configured for Android by default.
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# This was configured for Android by default.
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
答案 2 :(得分:0)
XStream似乎对EnclosingMethod属性进行了反思,因此将其保留在ProGuard配置中可能有所帮助:
-keepattributes EnclosingMethod
ProGuard manual提供了您可能希望保留的属性列表。错误消息表明您已经保留了InnerClasses
属性,这可能确实是必需的。