V6078. Potential Java SE API compatibility issue.
- IntellJ IDEA
- Плагин для Gradle
- Плагин для Maven
- Использование ядра напрямую
- Пример срабатываний диагностики V6078
Данное диагностическое правило позволяет обнаружить Java SE API в вашем коде, которые будут удалены или помечены как устаревшие в более новых версиях Java SE.
Когда выходят новые версии Java SE, то они, как правило, обратно совместимы с более ранними версиями, то есть, например, приложение, разработанное на основе Java SE 8, должно без проблем запуститься на 11 версии Java. Однако, между различными версиями API Java SE могут быть небольшие несовместимости. Эти несовместимости заключаются в том, что некоторые API претерпевают изменения: удаляются методы и классы, меняется их поведение, методы помечаются как устаревшие, и так далее.
Если у вас в компании строго с предупреждениями компилятора, то часть проблем можно не откладывая решить - например, не использовать метод или класс, который помечен как устаревший. Это полезно делать, так как есть вероятность, что при использовании вновь вышедшей версии Javа ваше приложение поведет себя неожидаемым образом или вовсе упадет.
Также в комплекте JDK есть инструмент 'jdeps', который поможет вам обнаружить зависимость вашего приложения от внутренних API JDK. Но такой инструмент запускают, как правило, когда встает вопрос о миграции вашего приложения на более свежую версию Java. А этим вопросом хорошо бы озадачиться еще тогда, когда вы просто пишете код, и не завязываться на API, которое будет удалено в следующих выпусках Java SE.
Диагностика V6078 заранее предупредит вас о том, что ваш код зависим от некоторых функций и классов Java SE API, которые на следующих версиях Java могут доставить вам трудности. Например, вы столкнётесь с такими трудностями, когда обнаружится, что ваше приложение падает у вашего клиента на более свежей версии Java. С большой вероятностью вам рано или поздно в какой-то момент придётся очищать код от использования старых API - лучше делать это регулярно, а не накапливать технический долг на будущее.
Диагностическое правило выдает предупреждения в следующих случаях:
- Если метод/класс/пакет удалены в целевой версии Java;
- Если метод/класс/пакет помечены как устаревшие в целевой версии Java;
- Если у метода изменилась сигнатура.
Правило на данный момент позволяет проанализировать совместимость Oracle Java SE c 8-ой по 14-ую версии. Диагностика V6078 по умолчанию выключена., Чтобы она заработала, её необходимо активировать и настроить.
IntellJ IDEA
В IntelliJ IDEA плагине вам необходимо во вкладке Settings > PVS-Studio > API Compatibility Issue Detection включить правило и указать параметры, а именно:
- Source Java SE – версия Java, на которой разработано ваше приложение.
- Target Java SE – версия Java, на совместимость с которой вы хотите проверить API, используемое в вашем приложении (Source Java SE)
- Exclude packages – пакеты, которые вы хотите исключить из анализа совместимости (пакеты перечисляются через запятую)
Плагин для Gradle
Используя gradle плагин, вам необходимо сконфигурировать настройки анализатора в build.gardle:
apply plugin: com.pvsstudio.PvsStudioGradlePlugin
pvsstudio {
....
compatibility = true
sourceJava = /*version*/
targetJava = /*version*/
excludePackages = [/*pack1, pack2, ...*/]
}
Плагин для Maven
Используя maven плагин, вам необходимо сконфигурировать настройки анализатора в pom.xml:
<build>
<plugins>
<plugin>
<groupId>com.pvsstudio</groupId>
<artifactId>pvsstudio-maven-plugin</artifactId>
....
<configuration>
<analyzer>
....
<compatibility>true</compatibility>
<sourceJava>/*version*/</sourceJava>
<targetJava>/*version*/</targetJava>
<excludePackages>/*pack1, pack2, ...*/</excludePackages>
</analyzer>
</configuration>
</plugin>
</plugins>
</build>
Использование ядра напрямую
Если вы используете анализатор напрямую через командную строку, то, чтобы активировать анализ совместимости выбранных Java SE API, необходимо использовать следующие параметры:
java -jar pvs-studio.jar /*other options*/ --compatibility
--source-java /*version*/ --target-java /*version*/
--exclude-packages /*pack1 pack2 ... */
Пример срабатываний диагностики V6078
Давайте предположим, что мы разрабатываем приложение на базе Java SE 8 и у нас есть класс со следующим содержимым:
/* imports */
import java.util.jar.Pack200;
public class SomeClass
{
/* code */
public static void someFunction(Pack200.Packer packer, ...)
{
/* code */
packer.addPropertyChangeListener(evt -> {/* code */});
/* code */
}
}
Запустив статический анализ с различными параметрами настройки диагностического правила, мы будем наблюдать следующую картину:
- Source Java SE – 8, Target Java SE – 9
- The 'addPropertyChangeListener' method will be removed.
- Source Java SE – 8, Target Java SE – 11
- The 'addPropertyChangeListener' method will be removed.
- The 'Pack200' class will be marked as deprecated.
- Source Java SE – 8, Target Java SE – 14
- The 'Pack200' class will be removed.
Сначала в Java SE 9 был удален метод 'addPropertyChangeListener' в классе 'Pack200.Packer'. В 11 версии к этому добавился тот факт, что класс 'Pack200' пометили как устаревший. А в 14 версии и вовсе этот класс был удален.
Поэтому, запустив приложение на Java 11, вы получите 'java.lang.NoSuchMethodError', а если запустите на Java 14 – 'java.lang.NoClassDefFoundError'.
Зная эту информацию, при разработке своего приложения, вы заранее будете знать о потенциальных проблемах при использовании такого API, и сможете сразу рассмотреть возможность использовать альтернативное API для решения поставленной задачи.