Совместимость и область защиты
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
Параметры, заданные вами явно, всегда важнее автоматических рекомендаций. Сканирование — это статический эвристический анализ: пометка «требуется проверка» не означает, что приложение обязательно откажет, а отчёт без замечаний не заменяет регрессионное тестирование на целевой платформе.
Когда сканирование требует правки кода
Если в отчёте появляется ACTION REQUIRED, придётся менять исходный код приложения: никакой набор параметров сборки этого не решит. В отчёте указаны конкретные классы и методы, а также одна из таких рекомендаций:
- Чтение ZIP или JAR из памяти: замените
ByteArrayInputStreamна файловый способ — напримерFiles.newInputStream(Path),FileInputStream,ZipFileилиJarFile. - Определение класса из необработанных байтов: не вызывайте
ClassLoader#defineClassдля защищённого класса. ИспользуйтеClass.forName()илиClassLoader.loadClass()и позвольте среде выполнения P4JX загрузить его.
После правки кода пересоберите JAR или WAR и повторите сканирование. Создавайте защищённый пакет только тогда, когда отчёт перестанет указывать на эту проблему.
2. Рекомендуемая модель защиты
публичная граница / точка входа фреймворка → обычный фасад или интерфейс → защищённая основная реализация
Например:
--protect 'com.example.service.impl.**' \
--exclude 'com.example.dto.**,com.example.config.**'
3. Классы, которые обычно не стоит защищать
- контроллеры, сервлеты, фильтры, слушатели и классы advice;
- классы конфигурации Spring и объекты, дополненные AOT или CGLIB;
- DTO для Jackson, record-классы, сущности JPA и модели сериализации;
- мосты JNI, SWT и другие нативные прослойки;
- классы, которые переписывает или переопределяет агент, ORM, библиотека моков, средство горячей перезагрузки или собственный ClassLoader;
- сторонние фреймворки и зависимости с открытым исходным кодом;
- классы, которым нужно читать собственный настоящий байт-код.
4. Неподдерживаемые и ограниченные возможности JVM
Среда выполнения
- Защищённое приложение должно работать на VLX JRE, поставляемой вместе с ним.
- Запуск через форму
-mиз JPMS и запуск из одного файла исходного кода не поддерживаются. - Обычные JAR в пути классов должны быть зарегистрированы упаковщиком; произвольно добавлять их при развёртывании нельзя.
- Не запускайте на VLX JRE незащищённые приложения.
Отладка и агенты
- JVMTI, отладчики JDWP, профилировщики, средства покрытия и большинство агентов APM не поддерживаются.
-javaagent,-agentlib, горячая перезагрузка и переопределение классов не поддерживаются.- Любое внедрение в байт-код должно быть завершено до кодирования.
Оптимизация запуска
- CDS, AppCDS и AOT не поддерживаются.
- ZGC и Shenandoah GC выходят за рамки среды выполнения P4JX.
5. Ресурсы классов и сканеры
При чтении ресурса .class защищённого класса возвращается заготовка метаданных: имя класса, сигнатуры и аннотации сохраняются, но настоящих тел методов там нет.
- Обычная рефлексия читает метаданные, но не восстанавливает исходный байт-код.
- Средства, которые сами разбирают физический ZIP, по умолчанию не видят содержимое архива P4JX; попробуйте
--zip-overlay scanner. - Сканерам пути классов вроде ClassGraph и Reflections в Spring Boot может понадобиться
--layout fat. - Разбор архива P4JX из потока в памяти или из сети через
ZipInputStreamлибоJarInputStreamне поддерживается. - Представление zipfs доступно только для чтения, изменять архив через него нельзя.
6. Поведение архива
- Суффикс
.jarне делает файл обычным JAR: содержимое остаётся форматом P4JX. - Многоверсионные JAR при кодировании сводятся к целевой версии Java.
- Подписи и семантика сертификатов исходного JAR не сохраняются; при необходимости подпишите итоговый результат отдельно для распространения.
- Не изменяйте, не пересжимайте и не объединяйте созданные файлы P4JX.