互換性スキャンと保護範囲

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)FileInputStreamZipFile、または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を使用して実行してはいけません。

デバッグおよびエージェント

  • JVMTI、JDWPデバッガ、パフォーマンス分析ツール、カバレッジツール、およびほとんどのAPMエージェントはサポートされていません。
  • -javaagent-agentlib、ホットリロード、クラスの再定義はサポートされていません。
  • バイトコードの織り込みが必要な処理は、コーディング前に完了させる必要があります。

起動最適化

  • CDS、AppCDS、AOTはサポートされていません。
  • ZGCおよびShenandoahGCは、P4JXの実行時でサポートされていません。

5. クラスリソースとスキャナー

保護されたクラスである.classのリソースを読み取ると、メタデータのみが取得されます。クラス名やシグネチャ、注釈は保持されますが、実際のメソッド本体は含まれません。

  • 通常のリフレクションではメタデータは読み取れますが、元のバイトコードを復元することはできません。
  • 物理的なZIPファイルを自動的に解析するツールでは、デフォルトではP4JXの内容が見えません。--zip-overlay scannerを試してみてください。
  • ClassGraphやReflectionsといったクラスパススキャナーは、Spring Boot環境下では--layout fatが必要になる場合があります。
  • ZipInputStream/JarInputStreamを使用してメモリやネットワークストリームからP4JXを解析することはサポートされていません。
  • zipfsビューは読み取り専用で、アーカイブを変更することはできません。

6. アーカイブ動作

  • .jarというサフィックスは通常のJARを意味せず、内容は依然としてP4JXです;
  • Multi-Release JARは、エンコード時にターゲットとなるJavaバージョンに応じて展開されます;
  • 元のJARの署名や証明書の意味は保持されず、必要に応じて最終的な配布物に対して外部で署名を行う必要があります;
  • 生成されたP4JXファイルを修正したり、再圧縮したり、結合したりしてはいけません。