我想打包一段绝对必须在Java 1.5上运行的代码。如果VM是1.6 VM,那么代码的一部分可以“增强”程序。
基本上就是这种方法:
private long[] findDeadlockedThreads() {
// JDK 1.5 only supports the findMonitorDeadlockedThreads()
// method, so you need to comment out the following three lines
if (mbean.isSynchronizerUsageSupported())
return mbean.findDeadlockedThreads();
else
return mbean.findMonitorDeadlockedThreads();
}
在1.5上使用编译然后在1.6 上进行1.6方法调用最简单的方法是什么?
在过去,我通过编译一个独特的1.6类来做类似的事情,我将使用我的应用程序打包并在1.6上使用ClassLoader实例化(因为1.6 JVM非常适合混合0x32和0x31类),但是我认为它有点矫枉过正(有点痛苦,因为在构建过程中你必须构建0x31和0x32 .class文件)。
如果我想在1.5上编译上述方法,我该怎么办?也许使用反射,但然后如何(我根本不熟悉反射)
注意:如果您感到好奇,上述方法来自本文:http://www.javaspecialists.eu/archive/Issue130.html
(但我不想像在文章中那样“评论三行”,我想要在1.5和1.6上编译和运行)
答案 0 :(得分:3)
你不能在1.5上编译它,但你可以在1.6上编译,目标选项设置为1.5(这将产生1.5的字节代码),并在代码中使用反射来确定方法是否可用。 / p>
此代码将查找方法: mbean.getClass()。getMethod(“findDeadlockedThreads”,new Class [0]); 问题是,如果该方法不存在而不是简单地返回null或类似的东西,它会抛出NoSuchMethodException。这意味着,您需要这样的代码:
try
{
mbean.getClass().getMethod("findDeadlockedThreads", new Class<?>[0]);
return mbean.findDeadlockedThreads();
}
catch(NoSuchMethodException ex)
{
return mbean.findMonitorDeadlockedThreads();
}
这不是很好,因为它使用Exception来做出决定。那可能不是很快。另一种方法是使用getMethods,如果方法可用,则迭代返回的列表。那也不是很快。
编辑: Christopher Oezbek在评论中建议只检查方法是否存在一次并保存结果以避免Try-catch-block的开销。这是对的,也是一个很好的解决方案。 matt b警告说,Java-Compiler的target-option不会检查所使用的类和方法是否在Java 1.5下可用。这是正确的(否则它将无法工作,因为您希望针对1.6方法进行编译)这意味着,应该在1.5-VM下仔细测试该程序,以避免此问题。感谢您的同意。
答案 1 :(得分:2)
编译为1.5。
在您的代码中使用反射。您可以从Class接口获取Method对象;它有一个invoke方法,它将您的mbean实例作为参数。像这样:
Class c = mbean.getClass(); //也可以做YourClass.class来获得这个
方法m = c.getMethod(“findMonitorDeadLockedThreads”); //或任何其他方法(参数到 该方法使用Class ...第二个参数指定getMethod)
m.invoke(mbean)//使用您的实例
调用Method当然,你不必每次都这样做;在构造函数中设置Method引用,然后根据需要调用正确的引用。
答案 2 :(得分:1)
Maven让您可以使用个人资料轻松完成此操作。配置文件背后的想法是,您希望根据某些条件构建两种不同版本的东西。在此特定示例中,您可以定义jdk15
和jdk16
配置文件,指定要编译的JDK版本,并告诉它在jdk15配置文件中包含该类的一个副本,另一个在jdk16。
要开始使用,请参阅:
http://unserializableone.blogspot.com/2008/09/compile-and-test-with-different-jdk.html
这描述了如何解决问题的不同JDK版本部分。
要处理问题的第二部分,根据JDK版本使用不同的类定义,请参阅: