Skip to content

Improve exploded structure experience for efficient deployments #38276

Closed
@snicoll

Description

@snicoll

The reference guide has a section on unpacking the executable jar to get extra boost. It also has an additional hint for bypassing the bootlader with the impact on losing classpath ordering.

Our work on AppCDS (see spring-projects/spring-framework#31497) has shown that a predicable classpath has an impact on how effective the cache is going to be. Investigating a bit more, it looks doable to provide the above as a first class concept.

Here is a proposal that is hacking layertools with an additional extract2(sic) command: https://github.com/snicoll/spring-boot/tree/gh-38276

Ignoring the fact that this does use layertools for convenience, you can execute the following on any repackaged archive:

java -Djarmode=layertools -jar target/my-app-1.0.0-SNAPSHOT.jar extract2 --destination target/app

This creates a directory with the following structure:

target/app/
├── application
│   └── my-app-1.0.0-SNAPSHOT.jar
├── dependencies
│   ├── ...
│   ├── spring-context-6.1.0-RC2.jar
│   ├── spring-context-support-6.1.0-RC2.jar
│   ├── ...
└── run-app.jar

You can then run the app as follows (assuming you're in the same directory as the previous command):

java -jar target/app/run-app.jar

The run-app.jar has the following characteristics:

  • It starts the application class directly (no bootlader used)
  • The manifest defines a classpath with the same order as classpath.idx, with application/my-app-1.0.0-SNAPSHOT.jar being in front

my-app-1.0.0-SNAPSHOT.jar has some manifest entries of the original jar so that package.getImplementationVersion() continues to work.

The work on this prototype has led to a number of questions:

  • Layertools provide a Command infrastructure and several utilities related to extracting/copying that are not specific to layers. If we want to go the same route with a different jar mode, a significant number of classes should be copied/reimplemented. Perhaps a single jar with a public API and sub-packages for layertools and this new mode could be an option?
  • This work could potentially apply to layers themselves. Rather than having dependencies/BOOT-INF/lib and a layer for the bootloader, we could use the same exact structure. Or perhaps the structure above could become a layer configuration (where all libs go to dependencies).
  • It's hard for run-app.jar to have sensible File attributes. The command tries to respect the file attributes of files it extracts from the repackaged archive, but run-jar.jar is created on the spot.

We have confirmed that with the prototype, AppCDS is effective (close to 95% classes loaded from the cache).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions