Как я могу проверить связь между скомпилированным кодом Java? - PullRequest
6 голосов
/ 28 июля 2010

Вообще говоря, один набор кода (код клиента) связывается с другим (код API).Связывание Java обычно проверяется между .java и .class во время компиляции или между .class & .class во время выполнения.Однако в последнем случае проверка выполняется так же, как и при обнаружении неверных ссылок (т. Е. Она ленива).

Существует ли способ принудительной проверки всех ссылок между клиентским кодом и APIкод сразу с скомпилированным кодом?Цель состоит в том, чтобы убедиться, что клиентский код будет работать с данной версией API - даже если он был скомпилирован с другой.

(Конечно, одним из способов будет декомпиляция и перекомпиляция с API,но есть ли более прямой метод?)

Ответы [ 6 ]

1 голос
/ 28 июля 2010

Принудительная проверка ссылок затруднена из-за характера языка и реализации JVM.

Я полагаю, что обоснование этого вопроса заключается в предотвращении ошибок компоновки во время выполнения, и намерение сделать это очень обоснованно. Однако, если взглянуть на причину ошибок связывания с точки зрения JVM, то более или менее сложно принудительно выполнить проверку без какого-либо влияния на производительность.

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

(Я предполагаю, что) Большинство проектов (включая коммерческие) поэтому избегают принудительной проверки и вместо этого полагаются на системы управления сборкой и зависимостями, чтобы избежать боли. Больше комментариев в этом ТАКОМ вопросе ; может помочь ответ на выбор OSGi Framework.

0 голосов
/ 09 августа 2010

Я бы рекомендовал использовать инструмент байт-кода, такой как asm, для "посещения" кода и переопределения вашего посетителя visitMethodInsn . Затем используйте отражение в классе владельца, ища метод с указанным именем и подписью. Вам также нужно взглянуть на код операции инструкции вызова - это будет один из следующих типов: invokevirtual, invokeinterface, invokespecial и invokestatic. Обратите внимание, чтобы обратить внимание на различие между invokevirtual и invokeinterface; вызов invokevirtual not успешно вызовет метод интерфейса, а вызов invokeinterface not успешно вызовет метод, который не определен в интерфейсе.

0 голосов
/ 09 августа 2010

Исходя из этого вопроса и Alfresco Wiki , вы можете попробовать -Xcomp запустить тестовую JVM и предварительно скомпилировать классы, чтобы проверить, есть ли ошибка ссылки.

0 голосов
/ 04 августа 2010

Для того, что вам нужно, вы можете использовать инструмент, такой как JarJarDiff [1], и получить разницу между новой и старой версией jar API.Затем задача преобразуется в проверку того, что вы не используете ни один из несовместимых API.Хотя этот подход не автоматический, он привлекает ваше внимание к изменениям, а не только к двоичной совместимости.

Если вы просто хотите проверить двоичную совместимость, проще всего перекомпилировать проект с новым JAR.Немного сложнее (и гораздо более хрупко) сканировать путь к классам и вызывать каждый метод каждого класса в поисках исключений для связей.Обратите внимание, что этот наивный подход не будет проверять все возможные пути и дает небольшую выгоду.

[1] http://depfind.sourceforge.net/tasks/jarjardiff.html

0 голосов
/ 28 июля 2010

Можно анализировать код из классов Java по рефлексивности. Смотрите пакет java.reflect . Некоторые инструменты анализа используют эту функцию для получения информации о скомпилированном коде. Лучший пример, вероятно, FindBugs .

Этот API как предел, и я не думаю, что вы можете делать с ним то, что хотите. Если в методе вызывается зависимость, API отражения может найти метод, его параметры, но не может дать вам зависимые функции, используемые в этом методе.

Так что я думаю, что такого инструмента анализа не существует в Java.

Решение состоит в том, чтобы один раз предоставить код со всеми его зависимостями. В разработке инструменты управления жизненным циклом, такие как Maven, могут помочь вам, управляя зависимостями вашего проекта.

0 голосов
/ 28 июля 2010

Возможно, вы можете запустить тесты junit для API, указанного в jar в ClassPath, затем просто отключите jar для разных версий API и снова запустите тесты. Вы могли бы автоматизировать это легко.

...