Совместимость и область защиты

P4JX шифрует реализации методов защищённых классов и разрешает их чтение только VLX JRE, входящему в пакет, во время выполнения. Для сбалансирования уровня защиты и совместимости с фреймворком рекомендуется защищать только основную логику бизнеса; входы в фреймворк, DTO/сущности, классы, которые должны быть динамически сгенерированы или изменены фреймворком, а также сторонние зависимости не включаются в процесс защиты.

1. Сначала выполнить сканирование совместимости

Только сканирование, без вывода результатов:

p4j javaapp app.jar --compat-scan
p4j springboot app.jar --compat-scan
p4j tomcat app.war --compat-scan

Сканирование с применением консервативных рекомендаций:

p4j springboot app.jar dist --compat-apply

Явные настройки пользователя имеют приоритет над автоматическими рекомендациями. Сканирование представляет собой статический гибридный анализ; наличие проблемы, указанной в отчёте “Необходимо провести повторную проверку.”, не означает обязательной неудачи приложения; отсутствие проблем в отчёте также не заменяет тестирование на целевой платформе.

Когда результаты сканирования требуют изменения кода

Если в отчёте GUI отображается Требуется выполнение операции. (на английской версии интерфейса — ACTION REQUIRED), это означает: Пользователь должен внести изменения в исходный код приложения.; такие проблемы невозможно решить путём корректировки параметров пакетирования. В отчёте указываются конкретные классы и методы, требующие изменений, а также приводятся рекомендации по их устранению.

  • Чтение ZIP/JAR из памяти: Замените ByteArrayInputStream на способы чтения из файлов, такие как Files.newInputStream(Path), FileInputStream, ZipFile или JarFile.
  • Определение класса на уровне исходных байтов: Не вызывайте ClassLoader#defineClass напрямую для защищённых классов; вместо этого используйте Class.forName() или ClassLoader.loadClass(), чтобы загрузка классов происходила во время выполнения P4JX.

После изменения исходного кода соберите снова JAR/WAR и выполните сканирование на совместимость; только после того, как в отчёте больше не будет указано это проблема, создавайте пакет защиты.

2. Рекомендуемая модель защиты

Открытая граница/вход в фреймворк → обычное facade или интерфейс → защищённая основная реализация

Пример:

--protect 'com.example.service.impl.**' \
--exclude 'com.example.dto.**,com.example.config.**'

3. Классы, которые обычно не следует защищать

  • Controller, Servlet, Filter, Listener, Advice;
  • Конфигурация Spring, объекты, улучшенные с помощью AOT/CGLIB;
  • DTO Jackson, record, JPA Entity, модели сериализации;
  • Классы-мосты JNI/SWT/native;
  • Классы, переписанные/переопределённые с помощью Agent, ORM, Mock, теплой замены или пользовательского ClassLoader;
  • Сторонние фреймворки и open-source зависимости;
  • Классы, которым необходимо читать их реальный классовый байткод.

4. Неподдерживаемые или ограниченные возможности JVM

Среда выполнения

  • Защищённое приложение должно использовать VLX JRE, поставляемый вместе с пакетом;
  • Неподдерживается запуск по способу JPMS -m и запуск из одного файла с исходным кодом;
  • Обычные JAR-файлы, находящиеся в классовом пути, должны быть зарегистрированы инструментом пакетирования и не могут быть добавлены в процесс развертывания произвольно;
  • Не следует использовать VLX JRE для запуска незащищённых обычных приложений.

Отладка и агенты

  • Не поддерживаются отладчики JVMTI и JDWP, инструменты анализа производительности, инструменты измерения уровня покрытия кода и большинство агентов APM;
  • Не поддерживаются -javaagent, -agentlib, теплая перезагрузка и переопределение классов;
  • Обработка, требующая встраивания байт-кода, должна быть выполнена до кодирования.

Оптимизация запуска

  • Не поддерживаются CDS, AppCDS и AOT;
  • ZGC и ShenandoahGC не находятся в диапазоне поддержки движка P4JX.

5. Ресурсы классов и сканеры

При чтении ресурса .class класса с защитой получаются только метаданные: сохраняются имя класса, подпись и аннотации, но отсутствует реальное тело методов.

  • Обычный механизм рефлексии позволяет читать метаданные, но не восстанавливать исходный байт-код;
  • Инструменты для самостоятельной обработки физических ZIP-архивов по умолчанию не видят содержимое P4JX; можно попробовать использовать --zip-overlay scanner;
  • Для сканеров classpath, таких как ClassGraph и Reflections, в Spring Boot может потребоваться --layout fat;
  • Пара ZipInputStream/JarInputStream не поддерживает обработку P4JX из памяти или сетевого потока;
  • Виджет zipfs является только для чтения — изменить архив невозможно.

6. Поведение архивации

  • Суффикс .jar не означает обычный JAR; содержимое по-прежнему является P4JX;
  • При кодировании Multi-Release JAR файлы распаковываются в соответствии с целевой версией Java;
  • Семантика подписи оригинального JAR и сертификата не сохраняется; при необходимости финальный продукт должен быть подписан внешним способом;
  • Не изменяйте, не сжимайте заново и не объединяйте генерируемые файлы P4JX.