Java: самый простой способ упаковать код Java 1.5 и 1.6 - PullRequest
8 голосов
/ 15 марта 2010

Я хочу упаковать кусок кода, который абсолютно должен работать на Java 1.5. Есть одна часть кода, где программа может быть «улучшена», если виртуальная машина - 1.6 ВМ.

В основном это такой метод:

 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, который я бы упаковывал вместе с моим приложением и создавал экземпляр с использованием ClassLoader при работе на 1.6 (потому что 1.6 JVM прекрасно сочетает классы 0x32 и 0x31), но думаю, это немного излишне (и немного болезненно, потому что во время процесса сборки вам нужно создавать файлы 0x31 и 0x32 .class).

Как мне поступить, если я хочу скомпилировать вышеуказанный метод на 1.5? Может быть, с помощью отражения, но потом как (я совсем не знаком с отражением)

Примечание: если вам интересно, приведенный выше метод взят из этой статьи: http://www.javaspecialists.eu/archive/Issue130.html

(но я не хочу «комментировать три строки», как в статье, я хочу, чтобы это компилировалось и работало как на 1.5, так и на 1.6)

Ответы [ 3 ]

3 голосов
/ 15 марта 2010

Вы не можете скомпилировать это на 1.5, но вы можете скомпилировать на 1.6 с параметром target, установленным на 1.5 (который будет производить байт-код для 1.5), и в коде, используя отражение, чтобы выяснить, доступен ли метод.

Этот код будет искать метод: mbean.getClass (). getMethod ("findDeadlockedThreads", новый класс [0]); Проблема в том, что он генерирует исключение NoSuchMethodException, если метод отсутствует, а не просто возвращает ноль или что-то подобное. Это означает, что вам нужен код, подобный следующему:

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

Это не очень хорошо, потому что для принятия решения используется исключение. Это, вероятно, не очень быстро. Альтернатива - вместо этого использовать getMethods и перебирать возвращаемый список, если ваш метод доступен. Это тоже не очень быстро.

РЕДАКТИРОВАТЬ: Кристофер Oezbek предлагает в комментариях сделать проверку существования метода только один раз и сохранить результат, чтобы избежать накладных расходов для блока Try-catch. Это правильное и хорошее решение. matt b предупреждает, что опция target Java-Compiler не проверяет, доступны ли используемые классы и методы в Java 1.5. Это верно (а иначе это не сработает, потому что вы хотите скомпилировать по 1.6-методу), и это означает, что программа должна быть тщательно протестирована под 1.5-VM, чтобы избежать этой проблемы. Спасибо за ваши комментарии оба.

2 голосов
/ 15 марта 2010

Компиляция для 1.5.

В вашем коде используйте отражение.Вы можете получить объект Method из интерфейса Class;у него есть метод invoke, который принимает ваш экземпляр mbean в качестве параметра.Примерно так:

Class c = mbean.getClass ();// также можем сделать YourClass.class, чтобы получить это

Method m = c.getMethod ("findMonitorDeadLockedThreads");// или любой другой метод (параметры метода указываются с помощью параметра Class ... второй для getMethod)

m.invoke (mbean) // вызывает метод с вашим экземпляром

OfКонечно, вы не должны делать это каждый раз;установите ссылки на метод в конструкторе, а затем просто вызовите правильный по требованию.

1 голос
/ 15 марта 2010

Maven позволяет вам сделать это довольно легко с профилями. Идея, лежащая в основе профилей, заключается в том, что вы хотите создать две разные версии чего-либо на основе определенных критериев. В этом конкретном примере вы можете определить профиль jdk15 и jdk16, указать, с какой версией JDK компилироваться, и указать включить одну копию класса в профиль jdk15, а другую в jdk16.

Для начала см .:

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

Здесь описывается, как выполнить другую часть проблемы JDK.

Чтобы справиться со второй частью проблемы, используя другое определение класса в зависимости от версии JDK, смотрите это:

Maven - включение разных файлов во время сборки

...