互換性と保護範囲
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. 推奨する保護モデル
公開境界・フレームワークのエントリポイント → 通常のファサードまたはインターフェイス → 保護された中核実装
例:
--protect 'com.example.service.impl.**' \
--exclude 'com.example.dto.**,com.example.config.**'
3. 通常は保護すべきでないクラス
- コントローラー、サーブレット、フィルター、リスナー、アドバイス
- Spring の設定クラス、AOT や CGLIB で拡張されたオブジェクト
- Jackson の DTO、レコード、JPA エンティティ、シリアライズ用モデル
- JNI、SWT などのネイティブブリッジクラス
- エージェント、ORM、モック、ホットリロード、カスタム ClassLoader が書き換えたり再定義したりするクラス
- サードパーティのフレームワークとオープンソースの依存関係
- 自分自身の実際のバイトコードを読む必要があるクラス
4. 未対応または制限のある JVM 機能
実行環境
- 保護されたアプリケーションは、同梱の VLX JRE で実行する必要があります。
- JPMS の
-mによる起動と、単一ソースファイルからの起動には対応していません。 - クラスパス上の通常の 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が必要になることがあります。 ZipInputStreamやJarInputStreamでメモリストリームやネットワークストリームから P4JX を解析することには対応していません。- zipfs ビューは読み取り専用で、アーカイブを変更することはできません。
6. アーカイブの挙動
.jarというサフィックスでも通常の JAR ではなく、中身は P4JX のままです。- マルチリリース JAR は、エンコード時にターゲットの Java バージョンへ平坦化されます。
- 元の JAR の署名や証明書のセマンティクスは保持されません。配布時に必要であれば、最終成果物に対して別途署名してください。
- 生成された P4JX ファイルを変更、再圧縮、結合しないでください。