Protect Spring Boot Applications

springboot protects Spring Boot applications, handling BOOT-INF/classes, BOOT-INF/lib, the Spring Boot loader, and framework scanning.

1. Using the GUI

  1. On the application type page, select Spring Boot.

    Select Spring Boot

  2. Select the Spring Boot application to protect, the bundled Java version, and the target platforms, then choose simple or advanced mode.

    Select the input, Java version, target platform, and mode

  3. In advanced mode, choose the output layout, the dependency JARs to protect, the JavaFX settings, JVM options, and exclusion rules. Simple mode derives the layout and exclusions from the compatibility scan. For what each option does, see Protector4J Advanced Mode Settings.

    Configure the advanced Spring Boot options

  4. Select the output directory, review the summary, then click Run protection.

    Select the output directory and run protection

2. CLI examples

The shortest form:

p4j springboot app.jar dist

The p4jx-fat layout is used by default. To choose another layout explicitly:

p4j springboot app.jar dist --layout fat
p4j springboot app.jar dist --layout separate

Protecting only part of the application:

p4j springboot app.jar dist \
  --protect 'com.example.service.impl.**' \
  --exclude 'com.example.dto.**,com.example.config.**'

3. Output structure and layouts

p4jx-fat: the default, a single protected archive

dist/
├── app.p4jx              # app.jar with the jar archive suffix
├── vlxjre/
├── run.sh
├── run.command
└── run.bat

Characteristics:

  • The whole application ships as one P4JX archive;
  • The physical file is not a ZIP by default;
  • Spring Boot resources, nested dependencies, and metadata are served through a virtual JAR view;
  • It gives the widest protection scope, which suits applications that do not rely on third-party class path scanners.

fat: the Spring Boot compatibility layout

dist/
├── app.jar
├── app.p4jx              # app-protected.jar with the jar suffix
├── vlxjre/
└── run.*

Characteristics:

  • app.jar keeps the standard physical BOOT-INF structure;
  • The real implementations of the protected classes live in the P4JX archive beside it;
  • It suits applications that need to scan the physical Spring Boot JAR structure, such as those using ClassGraph or Reflections;
  • The two files depend on each other and must be updated and delivered together.

separate: the split compatibility layout

dist/
├── plain-launcher.jar
├── app.p4jx
├── lib/
├── vlxjre/
└── run.*

Characteristics:

  • The Spring Boot loader, unprotected classes, and dependencies are kept apart;
  • It suits older integration environments that require a flat lib/* class path;
  • The generated launcher preloads the protected classes;
  • New projects should prefer p4jx-fat, or whichever of p4jx-fat and fat the scanner recommends.

Choosing a layout

SituationRecommended layout
A standard Spring Boot servicep4jx-fat
The application actually uses a scanner such as ClassGraph or Reflectionsfat
You need a flat directory of external dependencies, or dependency files encrypted separatelyseparate
Not sureRun --compat-scan first

The ZIP overlay only helps tools that read the ZIP central directory directly. It is not a replacement for the physical Spring Boot structure that ClassLoader and class path scanners need.

4. Starting the application

./run.sh --spring.profiles.active=prod

On Windows:

run.bat --spring.profiles.active=prod

Do not replace the vlxjre directory in the output with a system JRE.

For Windows targets you can also generate a native launcher. It works with all three layouts and coexists with the startup scripts — see Create a Windows EXE Launcher.

JVM startup options

You can fix JVM options at packaging time, either one per line under JVM startup options in the GUI, or on the command line:

p4j springboot app.jar dist \
  --jvm-option -Xms1g \
  --jvm-option -Xmx2g

To add options for a single run of a deployed package:

APP_JAVA_OPTS="-Duser.timezone=Asia/Shanghai" ./run.sh

You can also edit the deployed script directly:

  • macOS and Linux: in run.sh, add JVM_OPTS+=("-Xms1g" "-Xmx2g") after the generated JVM_OPTS=(...) and JVM_OPTS+=(...) lines.
  • Windows: in run.bat, add set "JVM_OPTS=%JVM_OPTS% -Xms1g -Xmx2g" after the generated set "JVM_OPTS=..." line.

Do not remove the options the packager generated for Spring Boot or JavaFX, such as --add-opens and the module path. Packaging again overwrites any manual edits — see JVM Startup Options for details.

5. Protection scope

By default, the application classes under BOOT-INF/classes are protected. These Spring-related classes are usually better left unprotected:

  • @Controller, @RestController, and @ControllerAdvice classes;
  • @Configuration classes, auto-configuration classes, and AOT- or CGLIB-enhanced classes;
  • Jackson DTOs, JPA entities, records, and validation models;
  • The application entry point and any class the framework constructs or proxies directly;
  • Classes that need runtime bytecode enhancement.

Protect the service implementations and reach them through a public facade or interface. Rules accept exact class names as well as pkg.* and pkg.**.

6. Protecting dependency JARs

--protect-lib protects the matching dependencies in BOOT-INF/lib, and works with all three layouts.

p4j springboot app.jar dist \
  --protect-lib 'company-core-*.jar,pricing-*.jar'

Protect your own closed-source dependencies only. Do not encrypt third-party framework packages such as Spring, Tomcat, logging libraries, or database drivers in the hope of "protecting more".

7. Compatibility scanning

p4j springboot app.jar --compat-scan
p4j springboot app.jar dist --compat-apply

The two options cannot be used together. They differ as follows:

OptionWhat it doesWhen to use it
--compat-scanScans the input JAR, prints the risks and configuration recommendations, and exits. It does not encode anything and does not produce dist, so no output directory is needed.Read the report first when you protect an application for the first time, after upgrading Spring Boot or another dependency, after changing the protection scope or layout, and when investigating a compatibility problem.
--compat-applyScans, merges in the conservative recommendations, then continues encoding and writes the output, so an output directory is required.Use it to finish packaging once you have read the scan results and accepted the recommendations. It also suits repeat builds and CI pipelines where the rules are already verified.

For springboot, --compat-apply can choose the layout, add exclusion patterns, and adjust the ZIP overlay, JavaFX, and archive suffix options. For everything other than the exclusions, a value given explicitly on the command line wins. Recommended exclusions are merged into your explicit --exclude patterns by default; pass --no-compat-excludes as well if you do not want them added. The scanner only performs static heuristic analysis, so problems that require source changes are not fixed by --compat-apply, and the packaged application still needs regression testing on the target platform.

For the other CLI commands, the full option list, environment variables, and automation examples, see the CLI Reference.