java ProGuard删除(收缩)未使用的类

假设我有这个Java应用程序:

package com.site; public class MyAppBase {} 

 package com.site.free; import com.site.MyAppBase; public class MyApp extends MyAppBase {} 

 package com.site.pro; import com.site.MyAppBase; public class MyApp extends MyAppBase {} 

 package com.site; public class Edition { public static final int FREE = 1; public static final int PRO = 2; private static final int EDITION = PRO; public static boolean is(final int edition) { return (EDITION == edition); } } 

 package com.site; public class EditionFactory { public static MyAppBase get_app() { MyAppBase ret = null; if (Edition.is(Edition.FREE)) ret = new com.site.free.MyApp(); else if (Edition.is(Edition.PRO)) ret = new com.site.pro.MyApp(); return ret; } } 

现在,ProGuard配置的任何组合我试图摆脱未选择的版本(在这种情况下它是免费的)不起作用。

通过“摆脱”我的意思是让实际的类消失(以及从调用代码)。

换句话说,这样的调用:

 final MyAppBase app = EditionFactory.get_app(); 

..在ProGuarding之后,目前正被翻译为:

 if (aa(1)) localObject5 = new c(); // <<< FREE else if (aa(2)) localObject5 = new d(); // <<< PRO 

..虽然我希望它被翻译成这个:

 localObject5 = new d(); // <<< PRO only in the code (as set at Edition.EDITION) 

底线是除了ProGuard很棒!! ),我似乎无法让它“透视”并理解Edition.is()是一个布尔函数,返回一个常量,可以删除一些类。

我尝试过以下配置:

 -keep,allowshrinking,allowoptimization public class * extends com.site.MyAppBase -optimizationpasses 10 

..什么都行不通

另一方面 ,如果我引用Edition.EDITION并将其内联比较(即没有任何“代理”函数),Java编译器(v1.6)会检测它并删除对非选定版本/类的整个引用。
这导致ProGuard删除/缩小未使用的类,这很好。

这里唯一的问题是关于维护 – 我很乐意继续使用EditionFactory风格。

由于ProGuard决定不内联Edition#is方法,因此无法执行优化,因此无法简化最终的一系列指令。 该方法没有内联,因为它不是很短,并且它也被多次调用。 您可以使用ProGuard的这个未记录的JVM选项解决第一个标准:

 -Dmaximum.inlined.code.length=16 

或者,您可以通过确保仅调用一次方法来解决第二个标准:

 return Edition.is(Edition.FREE) ? new com.site.free.MyApp() : new com.site.pro.MyApp(); 

或者,您可以创建短函数isFree()和isPro(),因为它们将返回常量,这将是内联的。

如果您期望进行某些特定的优化,那么检查已处理的代码是一种很好的做法,因为它们经常受到复杂的约束。

很高兴听到你喜欢ProGuard。

这是因为你的方法is(...)只能接受比1​​和2更多的值。 它可以从3,4,6的代码中调用其他地方…… Proguard不能排除这种情况。

您的问题的解决方案是使Edition成为enum 。 你不再需要is(...)方法,可以依赖equals(...)