相容性與保護範圍
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 Configuration、AOT/CGLIB 增強物件;
- Jackson DTO、record、JPA Entity、序列化模型;
- JNI/SWT/native 橋接類;
- 由 Agent、ORM、Mock、熱過載或自定義 ClassLoader 改寫/重新定義的類;
- 第三方框架和開源依賴;
- 需要讀取自身真實 class 位元組碼的類。
4. 不支援或受限的 JVM 能力
執行環境
- 受保護應用必須使用隨包 VLX JRE;
- 不支援 JPMS
-m方式啟動和單檔案原始碼啟動; - classpath 上的普通 JAR 必須由打包器登記,不能在部署時任意追加;
- 不應使用 VLX JRE 執行未保護的普通應用。
除錯和 Agent
- 不支援 JVMTI、JDWP 偵錯程式、效能分析器、覆蓋率和多數 APM agent;
- 不支援
-javaagent、-agentlib、熱過載和類重定義; - 需要位元組碼織入的處理應在編碼前完成。
啟動最佳化
- 不支援 CDS、AppCDS 和 AOT;
- ZGC 與 ShenandoahGC 不在 P4JX 執行時支援範圍內。
5. 類資源和掃描器
讀取保護類的 .class 資源時,獲得的是後設資料樁:保留類名、簽名和註解,不含真實方法體。
- 普通反射可讀取後設資料,但不能恢復原始位元組碼;
- 自行解析物理 ZIP 的工具預設看不到 P4JX 內容,可嘗試
--zip-overlay scanner; - ClassGraph、Reflections 等 classpath 掃描器在 Spring Boot 中可能需要
--layout fat; ZipInputStream/JarInputStream從記憶體或網路流解析 P4JX 不受支援;- zipfs 檢視只讀,不能修改歸檔。
6. 歸檔行為
.jar字尾不代表普通 JAR;內容仍是 P4JX;- Multi-Release JAR 在編碼時按目標 Java 版本展平;
- 原 JAR 簽名和證書語義不保留,需要時應對最終交付物做外部分發簽名;
- 不要修改、重壓縮或合併生成的 P4JX 檔案。