8

我想打包一段绝对必须在 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 上编译和运行)

4

3 回答 3

3

您不能在 1.5 上编译它,但您可以在 1.6 上编译,将 target-option 设置为 1.5(这将产生 1.5 的字节码)并在代码中使用反射来确定该方法是否可用。

此代码将查找方法: mbean.getClass().getMethod("findDeadlockedThreads", new Class[0]); 问题是,如果方法不存在,它会抛出 NoSuchMethodException 而不是简单地返回 null 或类似的东西。这意味着,您需要这样的代码:

try
{
  mbean.getClass().getMethod("findDeadlockedThreads", new Class<?>[0]);
  return mbean.findDeadlockedThreads();
}
catch(NoSuchMethodException ex)
{
  return mbean.findMonitorDeadlockedThreads();
}

这不是很好,因为它使用异常来做出决定。这可能不是很快。另一种方法是使用 getMethods 并在您的方法可用时迭代返回的列表。这也不是很快。

编辑: Christopher Oezbek 在评论中建议只检查一次方法的存在并保存结果以避免 Try-catch-block 的开销。这是正确的,也是一个很好的解决方案。matt b 警告,Java 编译器的目标选项不检查,如果使用的类和方法在 Java 1.5 下可用。没错(否则它将无法工作,因为您想针对 1.6 方法进行编译),这意味着该程序应该在 1.5 虚拟机下仔细测试,以避免这个问题。谢谢你们俩的意见。

于 2010-03-15T16:16:00.203 回答
2

编译为 1.5。

在您的代码中使用反射。可以从 Class 接口获取 Method 对象;它有一个将您的 mbean 实例作为参数的调用方法。像这样的东西:

类 c = mbean.getClass(); // 也可以做YourClass.class来得到这个

方法 m = c.getMethod("findMonitorDeadLockedThreads"); // 或任何其他方法(方法的参数用 Class 指定... getMethod 的第二个参数)

m.invoke(mbean) // 使用您的实例调用方法

当然,您不必每次都这样做;在构造函数中设置方法引用,然后按需调用正确的引用。

于 2010-03-15T16:17:59.040 回答
1

Maven 使您可以使用配置文件轻松完成此操作。配置文件背后的想法是,您希望根据某些标准构建事物的两个不同版本。在这个特定示例中,您可以定义 ajdk15和一个jdk16配置文件,指定使用哪个 JDK 版本进行编译,并告诉它在 jdk15 配置文件中包含该类的一个副本,而在 jdk16 中包含另一个副本。

要开始,请参阅:

http://unserializableone.blogspot.com/2008/09/compile-and-test-with-different-jdk.html

这描述了如何做不同的JDK版本部分的问题。

要处理问题的第二部分,根据 JDK 版本使用不同的类定义,请参见:

Maven - 在构建时包含不同的文件

于 2010-03-15T16:18:20.303 回答