如何在编译/运行时有条件地删除应用程序的一部分?
我有一个在嵌入式设备上运行的 Java 应用程序。由于不同的设备运行不同版本的设备 SDK,因此我必须针对大约 5 种不同的设备 SDK 组合进行构建。
其中一种组合不支持现有对象上的特定方法,并且从 SDK 中完全省略另一个对象。
我在程序中使用此方法和对象,但仅在特定配置中使用,因此我想在不支持它的设备上回退到另一个配置。
我很乐意在编译或运行时执行此后备行为。
有条件地删除此代码的最简单方法是什么?
代码在其他方面是相同的,因此我不想为这两个 SDK 创建两个单独的代码分支。
我使用 Ant 脚本构建我的应用程序。
如果相关的话,我的应用程序必须针对相当旧版本的 JDK (1.1.8/1.2) 进行构建。
I have a Java application which runs on an embedded device. Because different devices run different versions of the device SDKs I must build against ~5 different device SDK combinations.
One of these combinations does not support a specific method on an existing object and omits another object entirely from the SDK.
I use this method and object in my program, but only in a certain configuration, so I would like to just fallback to another configuration on devices which do not support it.
I would be happy to do this fallback behavior at compile or run time.
What's going to be the easiest way to conditionally remove this code?
The code is otherwise identical so I would prefer not to create two separate branches of code for the two SDKs.
I build my application using an Ant script.
My application has to build against a rather old version of the JDK (1.1.8/1.2) if that's relevant.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
@Lawrence Johnston 的自我回答概述了如何在构建时执行此操作。我认为这基本上是正确的想法,但您可能不希望插件 API 抛出已检查的异常。理想情况下,您希望旧平台的实现能够“尽最大努力”尝试执行请求的功能。
如果您想在运行时做出决定,您可以:
将类的不同版本放入单独的 JAR 文件中,并使用包装器脚本将适当的 JAR 包含在应用程序类路径中。
使用
Class.forName()
动态加载适合平台的类版本。无论哪种情况,您都需要确保基本应用程序类(旨在在所有平台上工作)不会静态地依赖于任何更高级的 SDK/JDK。
最后,我倾向于取消支持 Java 的旧版本。他们很多年前就“寿终正寝”了,而赡养他们的要求显然阻碍了你。例如,核心应用程序中向后兼容性的要求意味着它无法利用最近 Java 版本中添加的许多新功能。您有多少客户仍在使用那些古老的 Java 版本?为什么他们不能升级他们的平台?他们真的需要您的应用程序的最新版本吗?
@Lawrence Johnston's self-answer sketches how to do this at build time. I think this is basically the right idea, but you probably don't want the plugin API throwing checked exceptions. Ideally, you want implementations for the older platform to make a "best effort" attempt to perform the requested function.
If you want to make the decision at runtime you could:
put the different versions of the class into separate JAR files and use a wrapper script to include the appropriate JARs in the application classpath.
use
Class.forName()
to dynamically load the version of the class that is appropriate to the platform.In either case, you need to make sure that the base application classes (that are intended to work on all platforms) do not statically depend on any of the more advanced SDKs/JDKs.
Finally, I'd be inclined to desupport ancient versions of Java. They were "end-of-lifed" many years ago, and the requirement to support them is clearly holding you back. For instance, the requirement for backwards compatibility in your core application means that it cannot make use of the many new features added in recent Java releases. How many of your customers are still using those ancient Java releases? Why can't they upgrade their platform? Do they really need the latest version of your application?
一种想法是创建两个具有相同接口、完整实现和存根的类,两者都具有 isSupported() 方法,并且让存根中的所有其他方法抛出 UnsupportedOperationException。然后我可以在编译期间有条件地在 Ant 脚本中包含正确的类。
我选择使用这种方法而不是更动态的方法@Stephen C,因为它非常适合我们的目的,并且我们对设备(包括设备文件系统)的访问非常有限,使得部署多个jar、设置类路径变得困难, 将
我最终做的事情如下:
mypackagenamestub
并将要存根的文件复制到其中。确保您的 IDE 不会更改要存根的文件的包声明。omit.unsupportedmode
(释义)并在适当的情况下将其设置为 true。javac
的排除属性的值,例如**/MyPackageStub/**
或**/MyPackage/* *
基于omit.unsupportedmode
。One idea is to create two classes with the same interface, a full implementation and a stub, both with an isSupported() method and having all other methods in the stub throw an UnsupportedOperationException. Then I could conditionally include the correct class during compilation in my Ant script.
I elected to go with this rather than the more dynamic approach @Stephen C because it works perfectly well for our purposes and our access to the device (including the device filesystem) is quite limited, making it difficult to deploy multiple jars, set classpaths, etc.
What I ended up doing was as follows:
mypackagenamestub
and copy the files to be stubbed into it. Make sure that your IDE does not change the package declarations for the files to be stubbed.omit.unsupportedmode
(paraphrased) and set it to true where appropriate.javac
, e.g.**/MyPackageStub/**
or**/MyPackage/**
based onomit.unsupportedmode
.