配置Proguard以从Restlet库中去除未使用的类的最佳方法

时间:2013-10-19 01:27:30

标签: android proguard restlet

我在我的Android应用程序中使用Restlet 2.1.0 Java库进行HTTP和HTTPS通信。

到目前为止,我已经使用这些保留和忽略规则将Proguard配置为单独保留这些库:

-keep class org.restlet.** { *; }
-dontwarn org.restlet.**
-dontnote org.restlet.**

由于org.restlet.jar是726KB并且包含5761个方法,我现在尝试打开Proguard以删除我的应用程序不使用的所有代码,并安全地优化它。

不幸的是,我正在努力编写合适的Proguard规则,因为我的尝试会导致Exceptions,因为Restlet库使用反射。

我的规则的这些部分似乎足够安全:

-keep class org.restlet.engine.connector.Connection

# Ignore these Restlet warnings, as we have never included the
# org.jsslutils.* classes in our build
-dontwarn org.restlet.ext.ssl.**

我还试图移植我看到on this blog的规则:

-keep class org.restlet.engine.log.LoggerFacade
-keep class org.restlet.Application
-keep class org.restlet.Client
-keep class org.restlet.Context
-keep class org.restlet.* extends org.restlet.Client { *; }
-keep class org.restlet.* extends org.restlet.Context { *; }

不幸的是我一直在点java.lang.NoSuchMethodException这样:

10-18 18:22:12.975  3142  3165 W System.err: Exception during the instantiation of the client connector.
10-18 18:22:12.975  3142  3165 W System.err: java.lang.NoSuchMethodException: a(Client)
10-18 18:22:12.975  3142  3165 W System.err:    at java.lang.Class.getMatchingConstructor(Class.java:643)
10-18 18:22:12.975  3142  3165 W System.err:    at java.lang.Class.getConstructor(Class.java:472)
10-18 18:22:12.975  3142  3165 W System.err:    at org.restlet.engine.e.a(Engine.java:510)
10-18 18:22:12.975  3142  3165 W System.err:    at org.restlet.Client.<init>(Client.java:96)
10-18 18:22:12.975  3142  3165 W System.err:    at org.restlet.Client.<init>(Client.java:120)
10-18 18:22:12.975  3142  3165 W System.err:    at org.restlet.Client.<init>(Client.java:140)
10-18 18:22:12.975  3142  3165 W System.err:    at org.restlet.d.a.j(ClientResource.java:830)
10-18 18:22:12.975  3142  3165 W System.err:    at org.restlet.d.a.a(ClientResource.java:1045)
10-18 18:22:12.975  3142  3165 W System.err:    at org.restlet.d.a.a(ClientResource.java:1454)
10-18 18:22:12.985  3142  3165 W System.err:    at org.restlet.d.a.a(ClientResource.java:1400)

我正在使用我的Proguard mapping.txt和Restlet source code一个接一个地完成它们,但我想我现在要检查以防有人知道答案!

2 个答案:

答案 0 :(得分:2)

首先,我使用-dontobfuscate标志来运行Proguard而不进行混淆。我的例外情况仍然存在,但更容易看出原因:

10-20 08:43:06.725  4475  4499 W System.err: Error while handling an HTTP client call
10-20 08:43:06.725  4475  4499 W System.err: java.lang.NoSuchMethodException: ClientAdapter(Context)
10-20 08:43:06.725  4475  4499 W System.err:    at java.lang.Class.getMatchingConstructor(Class.java:643)
10-20 08:43:06.725  4475  4499 W System.err:    at java.lang.Class.getConstructor(Class.java:472)
10-20 08:43:06.725  4475  4499 W System.err:    at org.restlet.engine.adapter.HttpClientHelper.getAdapter(HttpClientHelper.java:100)
10-20 08:43:06.725  4475  4499 W System.err:    at org.restlet.engine.adapter.HttpClientHelper.handle(HttpClientHelper.java:111)
10-20 08:43:06.735  4475  4499 W System.err:    at org.restlet.Client.handle(Client.java:180)
10-20 08:43:06.735  4475  4499 W System.err:    at org.restlet.routing.Filter.doHandle(Filter.java:159)
10-20 08:43:06.735  4475  4499 W System.err:    at org.restlet.routing.Filter.handle(Filter.java:206)
10-20 08:43:06.735  4475  4499 W System.err:    at org.restlet.resource.ClientResource.handle(ClientResource.java:1137)
10-20 08:43:06.735  4475  4499 W System.err:    at org.restlet.resource.ClientResource.handleOutbound(ClientResource.java:1226)
10-20 08:43:06.735  4475  4499 W System.err:    at org.restlet.resource.ClientResource.handle(ClientResource.java:1069)
10-20 08:43:06.735  4475  4499 W System.err:    at org.restlet.resource.ClientResource.handle(ClientResource.java:1045)
10-20 08:43:06.735  4475  4499 W System.err:    at org.restlet.resource.ClientResource.post(ClientResource.java:1454)
10-20 08:43:06.735  4475  4499 W System.err:    at org.restlet.resource.ClientResource.post(ClientResource.java:1400)

我使用JD-GUI打开bin / proguard / obfuscated.jar并确认构造函数已被删除。缺少的构造函数在Adapter超类中。

public Adapter(Context context) {
    this.context = context;
}

针对该特定问题的修复是添加此Proguard规则:

-keep class org.restlet.engine.adapter.Adapter { *; }

使用简单的HTTP连接进行重建和测试,发现了我需要的更多规则。

使用以下规则可以让我成功建立HTTP和HTTPS连接。

# Preserve a minimal number of Restlet classes.  It is particularly
# difficult to get these keep rules correct as Restlet uses quite a
# lot of reflection. 
-keep class org.restlet.engine.log.LoggerFacade
-keep class org.restlet.Application
-keep class org.restlet.Client
-keep class org.restlet.Context
-keep class org.restlet.Connector
-keep class org.restlet.Request
-keep class org.restlet.Response
-keep class org.restlet.Restlet
-keep class org.restlet.data.Status
-keep class org.restlet.engine.adapter.Adapter { *; }
-keep class org.restlet.engine.adapter.ClientCall
-keep class org.restlet.engine.adapter.ClientAdapter { *; }
-keep class org.restlet.engine.adapter.HttpClientHelper { *; }
-keep class org.restlet.engine.connector.Connection
-keep class org.restlet.engine.ClientHelper { *; }
-keep class org.restlet.engine.header.Header { *; }

-keep class org.restlet.* extends org.restlet.Client { *; }
-keep class org.restlet.* extends org.restlet.Context { *; }
-keep class org.restlet.* extends org.restlet.Connector { *; }
-keep class org.restlet.* extends org.restlet.engine.ClientHelper { *; }
-keep class org.restlet.* extends org.restlet.resource.Resource { *; }

# We use constants like Disposition.NAME_FILENAME
-keepclassmembers class org.restlet.data.Disposition { public static final *; }

# Ignore these Restlet warnings, as we have never included the
# org.jsslutils.* classes in our build
-dontwarn org.restlet.ext.ssl.**

如果您对我使用不同的Restlet库,这些规则可能不适合您,但它们可能是一个有用的起点。

答案 1 :(得分:1)

经过多次试验和错误,这就是我正在使用的:

-keep class org.restlet.Application { *; }
-keep class org.restlet.Client { *; }
-keep class org.restlet.Connector { *; }
-keep class org.restlet.Context { *; }
-keep class org.restlet.Request { *; }
-keep class org.restlet.Response { *; }
-keep class org.restlet.Restlet { *; }
-keep class org.restlet.Server { *; }
-keep class org.restlet.Uniform { *; }
-keep class org.restlet.data.AuthenticationInfo { *; }
-keep class org.restlet.data.MediaType { *; }
-keep class org.restlet.data.CacheDirective { *; }
-keep class org.restlet.data.ChallengeRequest { *; }
-keep class org.restlet.data.ChallengeResponse { *; }
-keep class org.restlet.data.ChallengeScheme { *; }
-keep class org.restlet.data.CharacterSet { *; }
-keep class org.restlet.data.ClientInfo { *; }
-keep class org.restlet.data.Conditions { *; }
-keep class org.restlet.data.Digest { *; }
-keep class org.restlet.data.Disposition { *; }
-keep class org.restlet.data.Encoding { *; }
-keep class org.restlet.data.Expectation { *; }
-keep class org.restlet.data.Form { *; }
-keep class org.restlet.data.Language { *; }
-keep class org.restlet.data.Metadata { *; }
-keep class org.restlet.data.Method { *; }
-keep class org.restlet.data.Range { *; }
-keep class org.restlet.data.Reference { *; }
-keep class org.restlet.data.ReferenceList { *; }
-keep class org.restlet.data.Parameter { *; }
-keep class org.restlet.data.Protocol { *; }
-keep class org.restlet.data.ServerInfo { *; }
-keep class org.restlet.data.Status { *; }
-keep class org.restlet.data.Tag { *; }
-keep class org.restlet.engine.adapter.* { *; }
-keep class org.restlet.engine.log.LoggerFacade { *; }
-keep class org.restlet.engine.resource.AnnotationInfo { *; }
-keep class org.restlet.representation.Representation { *; }
-keep class org.restlet.representation.RepresentationInfo { *; }
-keep class org.restlet.representation.Variant { *; }
-keep class org.restlet.resource.* { *; }
-keep class org.restlet.security.Enroler { *; }
-keep class org.restlet.security.User { *; }
-keep class org.restlet.security.Verifier { *; }
-keep class org.restlet.service.ConnectorService { *; }
-keep class org.restlet.service.ConnegService { *; }
-keep class org.restlet.service.ConverterService { *; }
-keep class org.restlet.service.DecoderService { *; }
-keep class org.restlet.service.EncoderService { *; }
-keep class org.restlet.service.MetadataService { *; }
-keep class org.restlet.service.RangeService { *; }
-keep class org.restlet.service.StatusService { *; }
-keep class org.restlet.service.TaskService { *; }
-keep class org.restlet.service.TunnelService { *; }
-keep class org.restlet.util.Series { *; }
-keep class org.restlet.util.SelectionListener { *; }

Dan J的回复(对不起,这不适用于评论部分):

感谢您的建议。我刚刚尝试了上面的规则,我得到了这三个注释:

 [proguard] Note: the configuration keeps the entry point 'org.restlet.engine.connector.ConnectionPool { void clear(org.restlet.engine.connector.Connection); }', but not the descriptor class 'org.restlet.engine.connector.Connection'
 [proguard] Note: the configuration keeps the entry point 'org.restlet.representation.Representation { void setListener(org.restlet.util.ReadingListener); }', but not the descriptor class 'org.restlet.util.ReadingListener'
 [proguard] Note: the configuration keeps the entry point 'org.restlet.util.SelectionListener { void onSelected(org.restlet.util.SelectionRegistration); }', but not the descriptor class 'org.restlet.util.SelectionRegistration'

测试简单的HTTP连接会导致堆栈跟踪略有不同:

10-19 16:21:04.175  4042  4065 W System.err: Exception during the instantiation of the client connector.
10-19 16:21:04.175  4042  4065 W System.err: java.lang.NoSuchMethodException: a(Client)
10-19 16:21:04.175  4042  4065 W System.err:    at java.lang.Class.getMatchingConstructor(Class.java:643)
10-19 16:21:04.175  4042  4065 W System.err:    at java.lang.Class.getConstructor(Class.java:472)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.engine.e.a(Engine.java:514)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.Client.<init>(Client.java:96)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.Client.<init>(Client.java:120)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.Client.<init>(Client.java:140)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.resource.ClientResource.createNext(ClientResource.java:518)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.resource.ClientResource.getNext(ClientResource.java:830)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.resource.ClientResource.handleOutbound(ClientResource.java:1222)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.resource.ClientResource.handle(ClientResource.java:1069)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.resource.ClientResource.handle(ClientResource.java:1045)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.resource.ClientResource.post(ClientResource.java:1454)
10-19 16:21:04.185  4042  4065 W System.err:    at org.restlet.resource.ClientResource.post(ClientResource.java:1400)

我猜我们可能正在使用不同的Restlet版本,或者不同的基础Proguard配置?我注意到您使用的是*而不是**(例如org.restlet.engine.adapter.*),因此您的某些规则不会进入子包(docs)。

相关问题