如何修剪Java程序

时间:2011-06-18 03:22:01

标签: java aspectj variant pruning

让我从我想做的事情开始,然后提出一些问题。

我想开发一个通用的Java程序,它是许多程序的超集(让我们称之为程序变体)。特别地,通用程序具有仅由一个或多个程序变体(但不是全部)使用的方法。给定一个特定的配置,我想删除不必要的方法,并为一个程序变量保留最小的方法集。

例如,我有一个通用程序如下:

public class GeneralProgram {

    // this method is common for all variants
    public void method1() {};

    // this method is specific to variant 1
    public void method2() {};

    // this method is specific to variant 2
    public void method3() {};
}

然后在基于变体1的配置修剪程序之后,结果是

public class GeneralProgram {

    // this method is common for all variants
    public void method1() {};

    // this method is specific to variant 1
    public void method2() {};
}

结果类名称是否与原始类名称相同无关紧要。我只想修剪课程内容。

所以,这是我的问题:

  1. 除了低级文本处理之外,您是否知道如何实现这一点?

  2. 我知道我可以在运行时使用aspectJ来禁用/启用特定方法,但我真正想要做的是在部署程序之前执行此任务。为此目的,Java中是否有任何技术?

2 个答案:

答案 0 :(得分:6)

在我看来,正确的解决方案是使用一些面向对象的编程并将程序分层:

base.jar包含:

package foo.base;
class GeneralProgram {
   public void method1(){ }
}

var1.jar包含:

package foo.var1;
import foo.base.GeneralProgram;
class GeneralProgramVar1 extends GeneralProgram {
   public void method2(){ }
}

var2.jar包含:

package foo.var2;
import foo.base.GeneralProgram;
class GeneralProgramVar2 extends GeneralProgram {
   public void method3(){ }
}

某些部署将同时包含base.jar和var1.jar,其他部署将包含base.jar和var2.jar。你将不得不乱用类路径来解决依赖关系。


如果你可以很好地分离你的变种以便有真正未使用的函数,那么你可以使用像ProGuard之类的压缩实用程序来从类中删除未使用的方法。但是,您可能会发现,获得ProGuard优势所需的努力与我建议的结构相同。

答案 1 :(得分:3)

@Mark Elliot的回答为您提供了“正确的方法”。

有很多原因导致您的方式通常不是一个好主意,尤其是Java应用程序:

  • Java不支持此功能。具体来说,它不支持条件编译。

  • 虽然有时使用源代码预处理器,但主流Java工具链不支持它们。 (对于在字节码级别运行的(假设?)工具也是如此......虽然这不是你似乎在谈论的内容。)

  • 使用条件编译变体,在一个变体中进行更改会更容易破坏另一个变体。 (相比之下,一个好的O-O设计会将特定于变体的代码分离到特定的类,它们不会影响其他变体的行为。)

  • 使用猖獗的条件编译的代码库更难理解。

  • 条件编译变体使测试更复杂。您基本上必须将每个变体视为必须单独测试的单独应用程序。这使得编写测试更复杂,并且运行测试更加昂贵。 (并且测试变体很重要,因为依赖于条件编译的代码库的脆弱性;参见前面的内容。)

  • 由于工具问题,测试覆盖率分析更难/更多地使用变体;见前一页。


OP在评论中写道:

  

因此,如果我为特定变体部署不必要的资源(例如,特定于其他变体的方法,类),则无效。

你是什么意思“not effective”

在大多数情况下,代码库包含在某些用例或某些平台上未使用的功能并不重要。 Java应用程序使用大量内存,代码大小通常不是主要原因。简而言之,在大多数情况下部署不会使用的代码是“有效的”:它完成了工作并且开销不会真正重要。

如果您有其中一个异常应用程序,其中JAR文件大小或代码内存使用量非常重要(而不仅仅是假设问题),您仍然不需要求助于条件编译或字节码黑客。

  • 如果JAR文件大小是关键问题,那么有些工具会删除工具确定不会使用的类和方法;例如假设应用程序是从指定的main方法启动的。

  • 如果内存使用是关键问题,您可以构建代码,以便它使用动态加载来加载变体,平台甚至特定于用例的类。