Mitigate CDS image creation performance issues with long classpaths

PiperOrigin-RevId: 302929043
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/BUILD b/src/main/java/com/google/devtools/build/lib/rules/java/BUILD
index 3a22c66..d9bad25 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/BUILD
@@ -69,6 +69,7 @@
         "//src/main/java/com/google/devtools/build/lib/skylarkbuildapi",
         "//src/main/java/com/google/devtools/build/lib/skylarkbuildapi/core",
         "//src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java",
+        "//src/main/java/com/google/devtools/build/lib/vfs",
         "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
         "//third_party:guava",
         "//third_party:jsr305",
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java
index 1fcd622..9883c4d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java
@@ -22,8 +22,6 @@
 import com.google.common.collect.Lists;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
-import com.google.devtools.build.lib.actions.ParamFileInfo;
-import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.OutputGroupInfo;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
@@ -34,7 +32,6 @@
 import com.google.devtools.build.lib.analysis.RunfilesSupport;
 import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
 import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
-import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg;
 import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
 import com.google.devtools.build.lib.analysis.actions.LazyWritePathsFileAction;
 import com.google.devtools.build.lib.analysis.actions.SpawnAction;
@@ -58,6 +55,7 @@
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.util.Pair;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -523,6 +521,14 @@
             .addTransitive(attributes.getRuntimeClassPathForArchive())
             .build();
     Artifact jsa = ruleContext.getImplicitOutputArtifact(JavaSemantics.SHARED_ARCHIVE_ARTIFACT);
+    Artifact merged =
+        ruleContext.getDerivedArtifact(
+            jsa.getRootRelativePath()
+                .replaceName(
+                    FileSystemUtils.removeExtension(jsa.getRootRelativePath().getBaseName())
+                        + "-merged.jar"),
+            jsa.getRoot());
+    SingleJarActionBuilder.createSingleJarAction(ruleContext, classpath, merged);
     JavaRuntimeInfo javaRuntime = JavaRuntimeInfo.from(ruleContext);
     ruleContext.registerAction(
         new SpawnAction.Builder()
@@ -533,16 +539,12 @@
                     .addFormatted("-XX:SharedArchiveFile=%s", jsa.getExecPath())
                     .addFormatted("-XX:SharedClassListFile=%s", classlist.getExecPath())
                     .add("-cp")
+                    .addExecPath(merged)
                     .build())
-            .addCommandLine(
-                CustomCommandLine.builder()
-                    .addExecPaths(VectorArg.join(":").each(classpath))
-                    .build(),
-                ParamFileInfo.builder(ParameterFileType.UNQUOTED).build())
             .addOutput(jsa)
             .addInput(classlist)
+            .addInput(merged)
             .addTransitiveInputs(javaRuntime.javaBaseInputsMiddleman())
-            .addTransitiveInputs(classpath)
             .build(ruleContext));
     return jsa;
   }