Compatibility and Protection Scope
P4JX encrypts the method implementations of the classes you protect and lets only the VLX JRE shipped in the package read them at run time. To get good protection without breaking your frameworks, protect the core business logic only, and leave framework entry points, DTOs and entities, classes the framework generates or modifies at run time, and third-party dependencies out of scope.
1. Run a compatibility scan first
To scan without producing any output:
p4j javaapp app.jar --compat-scan
p4j springboot app.jar --compat-scan
p4j tomcat app.war --compat-scan
To scan and apply the conservative recommendations:
p4j springboot app.jar dist --compat-apply
Options you set explicitly always win over the automatic recommendations. The scan is a static heuristic analysis: a "review required" entry does not necessarily mean the application will fail, and a clean report is no substitute for regression testing on the target platform.
When the scan says the code has to change
If the GUI report shows ACTION REQUIRED, the application source itself must be changed — no combination of packaging options will resolve it. The report names the specific classes and methods involved and gives one of these recommendations:
- Reading a ZIP or JAR from memory: replace
ByteArrayInputStreamwith a file-based approach such asFiles.newInputStream(Path),FileInputStream,ZipFile, orJarFile. - Defining a class from raw bytes: do not call
ClassLoader#defineClasson a protected class. UseClass.forName()orClassLoader.loadClass()instead and let the P4JX runtime load it.
After changing the source, rebuild the JAR or WAR and run the compatibility scan again. Only build the protected package once the report no longer lists the problem.
2. Recommended protection model
public boundary / framework entry → ordinary facade or interface → protected core implementation
For example:
--protect 'com.example.service.impl.**' \
--exclude 'com.example.dto.**,com.example.config.**'
3. Classes you should normally leave unprotected
- Controllers, servlets, filters, listeners, and advice classes;
- Spring configuration classes and AOT- or CGLIB-enhanced objects;
- Jackson DTOs, records, JPA entities, and serialization models;
- JNI, SWT, and other native bridge classes;
- Classes that an agent, ORM, mocking library, hot-reload tool, or custom ClassLoader rewrites or redefines;
- Third-party frameworks and open source dependencies;
- Classes that need to read their own real bytecode.
4. JVM features that are unsupported or limited
Runtime environment
- A protected application must run on the VLX JRE shipped with it;
- Starting through the JPMS
-mform, or from a single source file, is not supported; - Ordinary JARs on the class path must be registered by the packager and cannot be added freely at deployment time;
- Do not use the VLX JRE to run unprotected applications.
Debugging and agents
- JVMTI, JDWP debuggers, profilers, coverage tools, and most APM agents are not supported;
-javaagent,-agentlib, hot reload, and class redefinition are not supported;- Any bytecode weaving must be finished before encoding.
Startup optimization
- CDS, AppCDS, and AOT are not supported;
- ZGC and Shenandoah GC are outside the scope of the P4JX runtime.
5. Class resources and scanners
Reading the .class resource of a protected class gives you a metadata stub: the class name, signatures, and annotations are preserved, but the real method bodies are not there.
- Ordinary reflection can read the metadata, but cannot recover the original bytecode;
- Tools that parse the physical ZIP themselves see nothing inside a P4JX archive by default — try
--zip-overlay scanner; - Class path scanners such as ClassGraph and Reflections may need
--layout fatunder Spring Boot; - Parsing a P4JX archive from a memory or network stream with
ZipInputStreamorJarInputStreamis not supported; - The zipfs view is read-only, so the archive cannot be modified through it.
6. Archive behavior
- A
.jarsuffix does not make it an ordinary JAR — the content is still P4JX; - Multi-release JARs are flattened to the target Java version during encoding;
- The original JAR signatures and certificate semantics are not preserved; sign the final deliverable separately if your distribution requires it;
- Do not modify, recompress, or merge the generated P4JX files.