Skip to content

Commit

Permalink
Introduce option to create uncompressed jars
Browse files Browse the repository at this point in the history
This is done by setting `quarkus.package.compress-jar`
to `false`.
This is a niche setting, but it can lead to slightly
reduced boot time when using uber-jar packaging

Closes: #38128
  • Loading branch information
geoand committed Jan 11, 2024
1 parent 6a50207 commit 1e992f1
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ public static BuiltInType fromString(String value) {
@ConfigItem(defaultValue = "jar")
public String type;

/**
* Whether the created jar will be compressed. This setting is not used when building a native image
*/
@ConfigDocDefault("false")
public Optional<Boolean> compressJar;

/**
* Manifest configuration of the runner jar.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ private void buildUberJar0(CurateOutcomeBuildItem curateOutcomeBuildItem,
MainClassBuildItem mainClassBuildItem,
ClassLoadingConfig classLoadingConfig,
Path runnerJar) throws Exception {
try (FileSystem runnerZipFs = ZipUtils.newZip(runnerJar)) {
try (FileSystem runnerZipFs = createNewZip(runnerJar, packageConfig)) {

log.info("Building uber jar: " + runnerJar);

Expand Down Expand Up @@ -530,7 +530,7 @@ private JarBuildItem buildLegacyThinJar(CurateOutcomeBuildItem curateOutcomeBuil
Files.deleteIfExists(runnerJar);
IoUtils.createOrEmptyDir(libDir);

try (FileSystem runnerZipFs = ZipUtils.newZip(runnerJar)) {
try (FileSystem runnerZipFs = createNewZip(runnerJar, packageConfig)) {

log.info("Building thin jar: " + runnerJar);

Expand Down Expand Up @@ -629,7 +629,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
if (!transformedClasses.getTransformedClassesByJar().isEmpty()) {
Path transformedZip = quarkus.resolve(TRANSFORMED_BYTECODE_JAR);
fastJarJarsBuilder.setTransformed(transformedZip);
try (FileSystem out = ZipUtils.newZip(transformedZip)) {
try (FileSystem out = createNewZip(transformedZip, packageConfig)) {
for (Set<TransformedClassesBuildItem.TransformedClass> transformedSet : transformedClasses
.getTransformedClassesByJar().values()) {
for (TransformedClassesBuildItem.TransformedClass transformed : transformedSet) {
Expand All @@ -650,7 +650,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
//now generated classes and resources
Path generatedZip = quarkus.resolve(GENERATED_BYTECODE_JAR);
fastJarJarsBuilder.setGenerated(generatedZip);
try (FileSystem out = ZipUtils.newZip(generatedZip)) {
try (FileSystem out = createNewZip(generatedZip, packageConfig)) {
for (GeneratedClassBuildItem i : generatedClasses) {
String fileName = i.getName().replace('.', '/') + ".class";
Path target = out.getPath(fileName);
Expand Down Expand Up @@ -683,7 +683,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
if (!rebuild) {
Predicate<String> ignoredEntriesPredicate = getThinJarIgnoredEntriesPredicate(packageConfig);

try (FileSystem runnerZipFs = ZipUtils.newZip(runnerJar)) {
try (FileSystem runnerZipFs = createNewZip(runnerJar, packageConfig)) {
copyFiles(applicationArchivesBuildItem.getRootArchive(), runnerZipFs, null, ignoredEntriesPredicate);
}
}
Expand All @@ -695,7 +695,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
if (!rebuild) {
copyDependency(parentFirstKeys, outputTargetBuildItem, copiedArtifacts, mainLib, baseLib,
fastJarJarsBuilder::addDep, true,
classPath, appDep, transformedClasses, removed);
classPath, appDep, transformedClasses, removed, packageConfig);
} else if (includeAppDep(appDep, outputTargetBuildItem.getIncludedOptionalDependencies(), removed)) {
appDep.getResolvedPaths().forEach(fastJarJarsBuilder::addDep);
}
Expand Down Expand Up @@ -768,7 +768,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
}
}
if (!rebuild) {
try (FileSystem runnerZipFs = ZipUtils.newZip(initJar)) {
try (FileSystem runnerZipFs = createNewZip(initJar, packageConfig)) {
ResolvedDependency appArtifact = curateOutcomeBuildItem.getApplicationModel().getAppArtifact();
generateManifest(runnerZipFs, classPath.toString(), packageConfig, appArtifact,
QuarkusEntryPoint.class.getName(),
Expand All @@ -783,7 +783,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
copyDependency(parentFirstKeys, outputTargetBuildItem, copiedArtifacts, deploymentLib, baseLib, (p) -> {
},
false, classPath,
appDep, new TransformedClassesBuildItem(Map.of()), removed); //we don't care about transformation here, so just pass in an empty item
appDep, new TransformedClassesBuildItem(Map.of()), removed, packageConfig); //we don't care about transformation here, so just pass in an empty item
}
Map<ArtifactKey, List<String>> relativePaths = new HashMap<>();
for (Map.Entry<ArtifactKey, List<Path>> e : copiedArtifacts.entrySet()) {
Expand Down Expand Up @@ -884,7 +884,8 @@ private Set<ArtifactKey> getRemovedKeys(ClassLoadingConfig classLoadingConfig) {
private void copyDependency(Set<ArtifactKey> parentFirstArtifacts, OutputTargetBuildItem outputTargetBuildItem,
Map<ArtifactKey, List<Path>> runtimeArtifacts, Path libDir, Path baseLib, Consumer<Path> targetPathConsumer,
boolean allowParentFirst, StringBuilder classPath, ResolvedDependency appDep,
TransformedClassesBuildItem transformedClasses, Set<ArtifactKey> removedDeps)
TransformedClassesBuildItem transformedClasses, Set<ArtifactKey> removedDeps,
PackageConfig packageConfig)
throws IOException {

// Exclude files that are not jars (typically, we can have XML files here, see https://github.com/quarkusio/quarkus/issues/2852)
Expand Down Expand Up @@ -912,7 +913,7 @@ private void copyDependency(Set<ArtifactKey> parentFirstArtifacts, OutputTargetB
// This case can happen when we are building a jar from inside the Quarkus repository
// and Quarkus Bootstrap's localProjectDiscovery has been set to true. In such a case
// the non-jar dependencies are the Quarkus dependencies picked up on the file system
packageClasses(resolvedDep, targetPath);
packageClasses(resolvedDep, targetPath, packageConfig);
} else {
Set<TransformedClassesBuildItem.TransformedClass> transformedFromThisArchive = transformedClasses
.getTransformedClassesByJar().get(resolvedDep);
Expand All @@ -934,8 +935,8 @@ private void copyDependency(Set<ArtifactKey> parentFirstArtifacts, OutputTargetB
}
}

private void packageClasses(Path resolvedDep, final Path targetPath) throws IOException {
try (FileSystem runnerZipFs = ZipUtils.newZip(targetPath)) {
private void packageClasses(Path resolvedDep, final Path targetPath, PackageConfig packageConfig) throws IOException {
try (FileSystem runnerZipFs = createNewZip(targetPath, packageConfig)) {
Files.walkFileTree(resolvedDep, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<Path>() {
@Override
Expand Down Expand Up @@ -1649,4 +1650,12 @@ public boolean decompile(Path jarToDecompile) {
}
}

private static FileSystem createNewZip(Path runnerJar, PackageConfig config) throws IOException {
boolean useUncompressedJar = config.compressJar.map(o -> !o).orElse(false);
if (useUncompressedJar) {
return ZipUtils.newZip(runnerJar, Map.of("compressionMethod", "STORED"));
}
return ZipUtils.newZip(runnerJar);
}

}

0 comments on commit 1e992f1

Please sign in to comment.