让我从我想做的事情开始,然后提出一些问题。
我想开发一个通用的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() {};
}
结果类名称是否与原始类名称相同无关紧要。我只想修剪课程内容。
所以,这是我的问题:
除了低级文本处理之外,您是否知道如何实现这一点?
我知道我可以在运行时使用aspectJ来禁用/启用特定方法,但我真正想要做的是在部署程序之前执行此任务。为此目的,Java中是否有任何技术?
答案 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
方法启动的。
如果内存使用是关键问题,您可以构建代码,以便它使用动态加载来加载变体,平台甚至特定于用例的类。