相容性與保護範圍

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)FileInputStreamZipFileJarFile 等基於檔案的讀取方式。
  • 從原始位元組定義類:不要對受保護類直接呼叫 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 檔案。