Skip to content

Commit 898a02a

Browse files
committed
removed dependencies level
1 parent 4b2fa15 commit 898a02a

File tree

6 files changed

+10
-90
lines changed

6 files changed

+10
-90
lines changed

core/deployment/src/main/java/io/quarkus/deployment/pkg/PackageConfig.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -183,33 +183,26 @@ interface JarConfig {
183183
boolean addRunnerSuffix();
184184

185185
/**
186-
* Whether to perform class reachability analysis and exclude non-reachable content
186+
* Whether to perform class reachability analysis and exclude non-reachable classes
187187
* from the produced JAR.
188188
* <ul>
189189
* <li>{@code none} - No analysis or exclusion is performed.</li>
190-
* <li>{@code dependencies} - Exclude entirely unused dependencies but keep all classes
191-
* within used dependencies.</li>
192-
* <li>{@code classes} - Exclude entirely unused dependencies and also exclude non-reachable
193-
* classes from used dependencies.</li>
190+
* <li>{@code classes} - Exclude non-reachable classes from dependencies.</li>
194191
* </ul>
195192
*/
196193
@WithDefault("classes")
197194
TreeShakeLevel treeShake();
198195

199196
/**
200-
* The level of dependency tree shaking to apply.
197+
* The level of tree shaking to apply.
201198
*/
202199
enum TreeShakeLevel {
203200
/**
204201
* No analysis or exclusion is performed.
205202
*/
206203
NONE,
207204
/**
208-
* Exclude entirely unused dependencies.
209-
*/
210-
DEPENDENCIES,
211-
/**
212-
* Exclude entirely unused dependencies and non-reachable classes from used dependencies.
205+
* Exclude non-reachable classes from dependencies.
213206
*/
214207
CLASSES
215208
}

core/deployment/src/main/java/io/quarkus/deployment/pkg/builditem/JarTreeShakeBuildItem.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,18 @@
1212
/**
1313
* Build item that holds the results of dependency usage analysis for tree shaking.
1414
* Contains the tree shake level, the set of reachable class names (dot-separated),
15-
* the set of artifact keys for dependencies that have at least one reachable class,
1615
* and the sorted list of removed class resource paths per dependency.
1716
*/
1817
public final class JarTreeShakeBuildItem extends SimpleBuildItem {
1918

2019
private final TreeShakeLevel level;
2120
private final Set<String> reachableClassNames;
22-
private final Set<ArtifactKey> usedDependencies;
2321
private final Map<ArtifactKey, List<String>> removedClasses;
2422

2523
public JarTreeShakeBuildItem(TreeShakeLevel level, Set<String> reachableClassNames,
26-
Set<ArtifactKey> usedDependencies,
2724
Map<ArtifactKey, List<String>> removedClasses) {
2825
this.level = level;
2926
this.reachableClassNames = reachableClassNames;
30-
this.usedDependencies = usedDependencies;
3127
this.removedClasses = removedClasses;
3228
}
3329

@@ -42,13 +38,6 @@ public Set<String> getReachableClassNames() {
4238
return reachableClassNames;
4339
}
4440

45-
/**
46-
* @return artifact keys of dependencies that have at least one reachable class
47-
*/
48-
public Set<ArtifactKey> getUsedDependencies() {
49-
return usedDependencies;
50-
}
51-
5241
/**
5342
* @return sorted list of removed class resource paths (e.g. "com/example/Foo.class") per dependency
5443
*/

core/deployment/src/main/java/io/quarkus/deployment/pkg/jar/AbstractFastJarBuilder.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -232,14 +232,6 @@ public JarBuildItem build() throws IOException {
232232
}
233233
final Map<ArtifactKey, List<Path>> copiedArtifacts = new HashMap<>();
234234
for (ResolvedDependency appDep : curateOutcome.getApplicationModel().getRuntimeDependencies()) {
235-
// When tree shake level is DEPENDENCIES, skip entirely unused dependencies.
236-
// At CLASSES level, keep all dependencies (only remove individual classes)
237-
// since they may still contribute non-class resources.
238-
if (treeShakeResult.getLevel() == PackageConfig.JarConfig.TreeShakeLevel.DEPENDENCIES
239-
&& !treeShakeResult.getUsedDependencies().contains(appDep.getKey())) {
240-
LOG.debugf("Tree shake: skipping unused dependency %s", appDep.getKey());
241-
continue;
242-
}
243235
if (!rebuild) {
244236
copyDependency(parentFirstArtifactKeys, outputTarget, copiedArtifacts, mainLib, baseLib,
245237
fastJarJarsBuilder::addDependency, fastJarJarsBuilder::addParentFirstDependency, true,

core/deployment/src/main/java/io/quarkus/deployment/pkg/jar/UberJarBuilder.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,6 @@ public JarBuildItem build() throws IOException {
140140
.build())
141141
.setRunnerPath(runnerJar);
142142
for (ResolvedDependency dep : curateOutcome.getApplicationModel().getDependencies()) {
143-
// At DEPENDENCIES level, unused deps are not packaged — exclude from manifest
144-
if (treeShakeResult.getLevel() == PackageConfig.JarConfig.TreeShakeLevel.DEPENDENCIES
145-
&& dep.isRuntimeCp()
146-
&& !treeShakeResult.getUsedDependencies().contains(dep.getKey())) {
147-
continue;
148-
}
149143
final ApplicationComponent.Builder comp = ApplicationComponent.builder()
150144
.setResolvedDependency(dep);
151145
if (!dep.getResolvedPaths().isEmpty()) {
@@ -200,15 +194,6 @@ private void buildUberJar0(Path runnerJar) throws IOException {
200194
continue;
201195
}
202196

203-
// When tree shake level is DEPENDENCIES, skip entirely unused dependencies.
204-
// At CLASSES level, keep all dependencies (only remove individual classes)
205-
// since they may still contribute non-class resources.
206-
if (treeShakeResult.getLevel() == PackageConfig.JarConfig.TreeShakeLevel.DEPENDENCIES
207-
&& !treeShakeResult.getUsedDependencies().contains(appDep.getKey())) {
208-
LOG.debugf("Tree shake: skipping unused dependency %s", appDep.getKey());
209-
continue;
210-
}
211-
212197
for (Path resolvedDep : appDep.getResolvedPaths()) {
213198
Set<String> transformedFilesByJar = transformedClasses.getTransformedFilesByJar().get(resolvedDep);
214199
if (transformedFilesByJar != null) {

core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarTreeShakeProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ void analyzeReachableClasses(
3232
if (treeShakeLevel == PackageConfig.JarConfig.TreeShakeLevel.NONE
3333
|| packageConfig.jar().type() == PackageConfig.JarConfig.JarType.MUTABLE_JAR) {
3434
treeShakeProducer
35-
.produce(new JarTreeShakeBuildItem(PackageConfig.JarConfig.TreeShakeLevel.NONE, Set.of(), Set.of(),
35+
.produce(new JarTreeShakeBuildItem(PackageConfig.JarConfig.TreeShakeLevel.NONE, Set.of(),
3636
Map.of()));
3737
return;
3838
}

core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarTreeShaker.java

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.util.Map;
1919
import java.util.Queue;
2020
import java.util.Set;
21-
import java.util.TreeMap;
2221
import java.util.function.Supplier;
2322

2423
import org.jboss.logging.Logger;
@@ -56,7 +55,6 @@ class JarTreeShaker {
5655

5756
private final Map<String, Supplier<byte[]>> appBytecode = new HashMap<>();
5857
private final Map<String, ArtifactKey> classToDep = new HashMap<>();
59-
private final Map<ArtifactKey, Integer> depClassCount = new HashMap<>();
6058
private final Map<String, Set<String>> serviceProviders = new HashMap<>();
6159
private final Map<String, Set<String>> serviceLoaderCalls = new HashMap<>();
6260
private final Set<String> sisuNamedClasses = new HashSet<>();
@@ -163,24 +161,6 @@ private JarTreeShakeBuildItem runInternal() {
163161
}
164162

165163
// Report
166-
167-
// Determine which dependencies have reachable classes
168-
final Map<ArtifactKey, Integer> depReachableCount = countReachableClasses(reachable);
169-
170-
final Set<ArtifactKey> usedDeps = new HashSet<>();
171-
final Map<ArtifactKey, int[]> usedDepsReport = new TreeMap<>(Comparator.comparing(ArtifactKey::toString));
172-
int unusedCount = 0;
173-
for (ResolvedDependency dep : appModel.getRuntimeDependencies()) {
174-
final ArtifactKey key = dep.getKey();
175-
int reached = depReachableCount.getOrDefault(key, 0);
176-
if (reached > 0) {
177-
usedDeps.add(key);
178-
usedDepsReport.put(key, new int[] { reached, depClassCount.getOrDefault(key, 0) });
179-
} else {
180-
unusedCount++;
181-
}
182-
}
183-
184164
log.info("============================================================");
185165
log.info(" Tree Shake: Dependency Usage Analysis");
186166
log.info("============================================================");
@@ -190,21 +170,16 @@ private JarTreeShakeBuildItem runInternal() {
190170
removedClassCount,
191171
totalDepClasses > 0 ? (removedClassCount * 100.0 / totalDepClasses) : 0.0,
192172
formatSize(removedBytes));
193-
log.infof(" Used dependencies : %d", usedDeps.size());
194-
log.infof(" Unused dependencies : %d", unusedCount);
195173
log.info("------------------------------------------------------------");
196174
log.info(" DEPENDENCIES WITH REMOVED CLASSES:");
197-
for (var entry : usedDepsReport.entrySet()) {
198-
int[] counts = entry.getValue();
199-
if (counts[0] < counts[1]) {
200-
log.infof(" - %s (%d / %d classes removed)",
201-
entry.getKey().toGacString(), counts[1] - counts[0], counts[1]);
202-
}
203-
}
175+
removedClassesPerDep.entrySet().stream()
176+
.sorted(Map.Entry.comparingByKey(Comparator.comparing(ArtifactKey::toGacString)))
177+
.forEach(e -> log.infof(" - %s (%d classes removed)",
178+
e.getKey().toGacString(), e.getValue().size()));
204179
log.info("============================================================");
205180
log.infof("Done in %s", (System.currentTimeMillis() - start));
206181

207-
return new JarTreeShakeBuildItem(treeShakeLevel, reachable, usedDeps, removedClassesPerDep);
182+
return new JarTreeShakeBuildItem(treeShakeLevel, reachable, removedClassesPerDep);
208183
}
209184

210185
private void collectRuntimeClasses() {
@@ -216,7 +191,6 @@ private void collectRuntimeClasses() {
216191
// Add all classes from quarkus-bootstrap-runner as roots (fast-jar runtime infrastructure)
217192
final boolean addClassesAsRoots = "quarkus-bootstrap-runner".equals(dep.getArtifactId());
218193

219-
final int[] classCount = new int[1];
220194
// Use walkRaw to get all entries including multi-release versions.
221195
// For multi-release entries, we pick the highest version <= appJavaVersion,
222196
// matching what JarFile.runtimeVersion() resolves at runtime.
@@ -254,7 +228,6 @@ private void collectRuntimeClasses() {
254228
int currentVersion = depBytecodeVersion.getOrDefault(className, -1);
255229
if (currentVersion < 0) {
256230
classToDep.put(className, dep.getKey());
257-
classCount[0]++;
258231
}
259232
if (classJavaVersion > currentVersion) {
260233
depBytecodeVersion.put(className, classJavaVersion);
@@ -283,7 +256,6 @@ private void collectRuntimeClasses() {
283256
parseSisuNamedFile(visit.getPath());
284257
}
285258
});
286-
depClassCount.put(dep.getKey(), classCount[0]);
287259
}
288260
}
289261

@@ -357,17 +329,6 @@ private void addStringClassReferenceRoots(Set<String> allKnownClasses) {
357329
}
358330
}
359331

360-
private Map<ArtifactKey, Integer> countReachableClasses(Set<String> reachable) {
361-
final Map<ArtifactKey, Integer> depReachableCount = new HashMap<>();
362-
for (String className : reachable) {
363-
ArtifactKey dep = classToDep.get(className);
364-
if (dep != null) {
365-
depReachableCount.merge(dep, 1, Integer::sum);
366-
}
367-
}
368-
return depReachableCount;
369-
}
370-
371332
private OpenPathTree openPathTree(ResolvedDependency dep) {
372333
var openPathTree = dep.getContentTree().open();
373334
openTrees.add(openPathTree);

0 commit comments

Comments
 (0)