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

时间:2011-08-15 02:11:27

标签: 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 (a.a(1))
    localObject5 = new c(); // <<< FREE
else if (a.a(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风格。

2 个答案:

答案 0 :(得分:7)

由于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。

答案 1 :(得分:1)

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

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