Compatibility and protection scope

P4JX encrypts and stores the method implementations of protected classes, allowing only the VLX JRE included in the package to read them at runtime. To balance protection effectiveness with framework compatibility, it is recommended to protect only the core business logic; framework entry points, DTOs/entities, classes that need to be dynamically generated or modified by the framework, and third-party dependencies should not be included in protection.

1. Run a compatibility scan first

Only scan, do not output:

p4j javaapp app.jar --compat-scan
p4j springboot app.jar --compat-scan
p4j tomcat app.war --compat-scan

Scan and apply conservative recommendations:

p4j springboot app.jar dist --compat-apply

Explicit user options take precedence over automatic recommendations. Scanning is a static heuristic analysis; a report of “Review is required.” does not necessarily mean failure to apply changes; a report indicating no issues also cannot replace regression testing on the target platform.

When code modification is required based on scan results

If the GUI report shows Actions are required. (ACTION REQUIRED in the English interface), it indicates Users must modify the application’s source code.; such issues cannot be resolved by adjusting packaging parameters. The report will list the specific classes and methods that need modification and provide one of the following handling suggestions:

  • Read ZIP/JAR from memory: Change ByteArrayInputStream to file-based reading methods such as Files.newInputStream(Path), FileInputStream, ZipFile, or JarFile.
  • Define classes from raw bytes: Do not call ClassLoader#defineClass directly on protected classes; instead, use Class.forName() or ClassLoader.loadClass() to allow P4JX to handle class loading at runtime.

After modifying the source code, rebuild the JAR/WAR file and run a compatibility scan again. Once the report no longer lists this issue, generate the protection package.

Public boundary/frame entry → regular facade or interface → protected core implementation

Example:

--protect 'com.example.service.impl.**' \
--exclude 'com.example.dto.**,com.example.config.**'

3. Classes that generally should not be protected

  • Controller, Servlet, Filter, Listener, Advice;
  • Spring Configuration, AOT/CGLIB enhanced objects;
  • Jackson DTOs, records, JPA Entities, serialization models;
  • JNI/SWT/native bridge classes;
  • Classes that have been overridden/redisigned by Agents, ORMs, Mocks, hot reloading, or custom ClassLoaders;
  • Third-party frameworks and open-source dependencies;
  • Classes that require reading their own actual class bytecode.

4. JVM capabilities that are not supported or are limited.

Runtime environment.

  • The protected application must use the VLX JRE included with the package.
  • Starting via the JPMS -m method and starting from a single-file source code are not supported.
  • Ordinary JARs in the classpath must be registered by the packer and cannot be added arbitrarily during deployment;
  • Unprotected ordinary applications should not be run using the VLX JRE.

Debugging and Agent

  • JVMTI, JDWP debuggers, performance analyzers, coverage tools, and most APM agents are not supported;
  • -javaagent, -agentlib, hot reloading, and class redefinition are not supported;
  • Bytecode weaving tasks must be completed before encoding.

Startup optimization

  • CDS, AppCDS, and AOT are not supported;
  • ZGC and ShenandoahGC are not within the support scope of the P4JX runtime.

5. Class resources and scanners

When reading the .class resources of protected classes, metadata stubs are obtained: the class names, signatures, and annotations are retained, but the actual method bodies are missing.

  • Regular reflection can read metadata, but it cannot restore the original bytecode.
  • Tools that parse physical ZIP files by themselves cannot see the contents of P4JX by default; try --zip-overlay scanner.
  • Classpath scanners such as ClassGraph and Reflections may require --layout fat in Spring Boot.
  • Parsing P4JX from memory or network streams using ZipInputStream/JarInputStream is not supported.
  • The zipfs view is read-only; the archive cannot be modified.

6. Archiving behavior

  • The .jar suffix does not indicate a regular JAR; the content remains P4JX;
  • Multi-Release JARs are flattened according to the target Java version during encoding;
  • The original JAR signature and certificate semantics are not preserved; external distribution signing should be applied to the final deliverable if necessary;
  • Do not modify, re-compress, or merge the generated P4JX files.