Java:打包 Java 1.5 和 1.6 代码的最简单方法

发布于 2024-08-25 04:35:19 字数 959 浏览 2 评论 0原文

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

I want to package a piece of code that absolutely must run on Java 1.5. There's one part of the code where the program can be "enhanced" if the VM is an 1.6 VM.

Basically it's this method:

 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();
  }

What would be easiest way to have this compile on 1.5 and yet do the 1.6 method calls when on 1.6 ?

In the past I've done something similar by compiling a unique 1.6 class that I would package with my app and instantiate using a ClassLoader when on 1.6 (because an 1.6 JVM is perfectly fine mixing 0x32 and 0x31 classes), but I think it's a bit overkill (and a bit painful because during the build process you have to build both 0x31 and 0x32 .class files).

How should I go if I wanted to compile the above method on 1.5? Maybe using reflection but then how (I'm not familiar at all with reflection)

Note: if you're curious, the above method comes from this article: http://www.javaspecialists.eu/archive/Issue130.html

(but I don't want to "comment the three lines" like in the article, I want this to compile and run on both 1.5 and 1.6)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

那请放手 2024-09-01 04:35:19

您无法在 1.5 上编译它,但可以在 1.6 上编译,并将目标选项设置为 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-VM 下仔细测试该程序,以避免出现此问题。感谢你们两位的评论。

You cannot compile this on 1.5, but you can compile on 1.6 with the target-option set to 1.5 (that would produce byte-code for 1.5) and in the code using reflection to find out if the method is available.

This code would lookup the method:
mbean.getClass().getMethod("findDeadlockedThreads", new Class[0]);
Problem is, it throws an NoSuchMethodException if the method isn't present instead of simply returning null or something similar. That means, you need code like this:

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

That's not very nice, because it uses an Exception to make an decision. That is probably not very fast. An alternative is to use getMethods instead and iterate over the returned list if your method is available. That's also not very fast.

EDIT: Christopher Oezbek suggests in the comments to make the check for the existence of the method only once and save the result to avoid the overhead for the Try-catch-block. That's right and a good solution. matt b warns, that the target-option of the Java-Compiler doesn't check, if the classes and methods used are available under Java 1.5. That's right (and otherwise it wouldn't work, because you want to compile against a 1.6-method) and that means, that the program should be carefully tested under a 1.5-VM, to avoid this problem. Thanks for your comments both of you.

救赎№ 2024-09-01 04:35:19

编译 1.5。

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

Class c = mbean.getClass(); // 也可以通过 YourClass.class 来获取此

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

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

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

Compile for 1.5.

In your code use reflection. You can get the Method object from the Class interface; it has an invoke method that takes your mbean instance as a parameter. Something like this:

Class c = mbean.getClass(); // can also do YourClass.class to get this

Method m = c.getMethod("findMonitorDeadLockedThreads"); // or any other method (parameters to
the method are specified with Class... second parameter to getMethod)

m.invoke(mbean) // invokes the Method with your instance

Of course you don't have to do this every time; setup the Method references in a constructor and then just invoke the right one on demand.

左岸枫 2024-09-01 04:35:19

Maven 可以让您通过配置文件轻松地完成此操作。配置文件背后的想法是,您希望根据某些标准构建两个不同版本的东西。在此特定示例中,您可以定义一个 jdk15 和一个 jdk16 配置文件,指定使用哪个 JDK 版本来编译每个配置文件,并告诉它在jdk15配置文件和jdk16中的其他配置文件。

要开始使用,请参阅:

http:// unserializedone.blogspot.com/2008/09/compile-and-test-with- Different-jdk.html

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

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

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

Maven lets you do this pretty easily with profiles. The idea behind profiles is that you want to build things two different versions of something based on some criteria. In this specific example, you can define a jdk15 and a jdk16 profile, specify which JDK version to compile each with, and tell it to include one copy of the class in the jdk15 profile and the other in jdk16.

To get started, see:

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

This describes how to do the different JDK version part of the problem.

To handle the second part of the problem, using a different definition of the class depending on the JDK version, see this:

Maven - Include Different Files at Build Time

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文