Make javac rules output a jar with soong_zip

Make javac rules output a jar file instead of a classes.list.
Combine the output jar, static jar dependencies, and resources
into the final jar using a separate rule.  For now, use a shell
command with unzip and soong_zip to create the final jar,
eventually it will be done with a zip2zip-style jar combiner.

Bug: 64691570
Test: java_test.go
Change-Id: Id8e6313e0097b78947d88e86e47b56ad08caca1a
diff --git a/java/builder.go b/java/builder.go
index e359529..c39bd4e 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -43,8 +43,8 @@
 				`$javacFlags $bootClasspath $classpath ` +
 				`-source $javaVersion -target $javaVersion ` +
 				`-d $outDir -s $annoDir @$out.rsp && ` +
-				`find $outDir -type f | sort | ${config.JarArgsCmd} $outDir > $out`,
-			CommandDeps:    []string{"${config.JavacCmd}", "${config.JarArgsCmd}"},
+				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
+			CommandDeps:    []string{"${config.JavacCmd}", "${config.SoongZipCmd}"},
 			Rspfile:        "$out.rsp",
 			RspfileContent: "$in",
 		},
@@ -57,12 +57,12 @@
 				`$javacFlags $bootClasspath $classpath ` +
 				`-source $javaVersion -target $javaVersion ` +
 				`-d $outDir -s $annoDir @$out.rsp && ` +
-				`find $outDir -type f | sort | ${config.JarArgsCmd} $outDir > $out`,
+				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
 			CommandDeps: []string{
 				"${config.JavaCmd}",
 				"${config.ErrorProneJavacJar}",
 				"${config.ErrorProneJar}",
-				"${config.JarArgsCmd}",
+				"${config.SoongZipCmd}",
 			},
 			Rspfile:        "$out.rsp",
 			RspfileContent: "$in",
@@ -71,17 +71,24 @@
 
 	jar = pctx.AndroidStaticRule("jar",
 		blueprint.RuleParams{
-			Command:     `${config.JarCmd} $operation ${out}.tmp $manifest $jarArgs && ${config.Zip2ZipCmd} -t -i ${out}.tmp -o ${out} && rm ${out}.tmp`,
-			CommandDeps: []string{"${config.JarCmd}"},
+			Command:     `${config.SoongZipCmd} -jar -o $out $jarArgs`,
+			CommandDeps: []string{"${config.SoongZipCmd}"},
 		},
-		"operation", "manifest", "jarArgs")
+		"jarArgs")
+
+	combineJar = pctx.AndroidStaticRule("combineJar",
+		blueprint.RuleParams{
+			Command:     `${config.MergeZipsCmd} -j $out $in`,
+			CommandDeps: []string{"${config.MergeZipsCmd}"},
+		},
+		"outDir")
 
 	dx = pctx.AndroidStaticRule("dx",
 		blueprint.RuleParams{
 			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
-				`${config.DxCmd} --dex --output=$outDir $dxFlags $in && ` +
-				`find "$outDir" -name "classes*.dex" | sort | ${config.JarArgsCmd} ${outDir} > $out`,
-			CommandDeps: []string{"${config.DxCmd}", "${config.JarArgsCmd}"},
+				`${config.DxCmd} --dex --output=$outDir $dxFlags $in || ( rm -rf "$outDir"; exit 41 ) && ` +
+				`find "$outDir" -name "classes*.dex" | sort > $out`,
+			CommandDeps: []string{"${config.DxCmd}"},
 		},
 		"outDir", "dxFlags")
 
@@ -91,22 +98,6 @@
 			CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
 		},
 		"rulesFile")
-
-	extractPrebuilt = pctx.AndroidStaticRule("extractPrebuilt",
-		blueprint.RuleParams{
-			Command: `rm -rf $outDir && unzip -qo $in -d $outDir && ` +
-				`find $outDir -name "*.class" | sort | ${config.JarArgsCmd} ${outDir} > $classFile && ` +
-				`find $outDir -type f -a \! -name "*.class" -a \! -name "MANIFEST.MF" | sort | ${config.JarArgsCmd} ${outDir} > $resourceFile`,
-			CommandDeps: []string{"${config.JarArgsCmd}"},
-		},
-		"outDir", "classFile", "resourceFile")
-
-	fileListToJarArgs = pctx.AndroidStaticRule("fileListToJarArgs",
-		blueprint.RuleParams{
-			Command:     `${config.JarArgsCmd} -f $in -p ${outDir} -o $out`,
-			CommandDeps: []string{"${config.JarjarCmd}"},
-		},
-		"outDir")
 )
 
 func init() {
@@ -123,23 +114,19 @@
 }
 
 type jarSpec struct {
-	android.ModuleOutPath
+	fileList, dir android.Path
 }
 
-func (j jarSpec) jarArgs() string {
-	return "@" + j.String()
+func (j jarSpec) soongJarArgs() string {
+	return "-C " + j.dir.String() + " -l " + j.fileList.String()
 }
 
-func (j jarSpec) path() android.Path {
-	return j.ModuleOutPath
-}
-
-func TransformJavaToClasses(ctx android.ModuleContext, srcFiles android.Paths, srcFileLists android.Paths,
-	flags javaBuilderFlags, deps android.Paths) jarSpec {
+func TransformJavaToClasses(ctx android.ModuleContext, srcFiles, srcFileLists android.Paths,
+	flags javaBuilderFlags, deps android.Paths) android.ModuleOutPath {
 
 	classDir := android.PathForModuleOut(ctx, "classes")
 	annoDir := android.PathForModuleOut(ctx, "anno")
-	classFileList := android.PathForModuleOut(ctx, "classes.list")
+	classJar := android.PathForModuleOut(ctx, "classes.jar")
 
 	javacFlags := flags.javacFlags + android.JoinWithPrefix(srcFileLists.Strings(), "@")
 
@@ -148,7 +135,7 @@
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 		Rule:        javac,
 		Description: "javac",
-		Output:      classFileList,
+		Output:      classJar,
 		Inputs:      srcFiles,
 		Implicits:   deps,
 		Args: map[string]string{
@@ -161,7 +148,7 @@
 		},
 	})
 
-	return jarSpec{classFileList}
+	return classJar
 }
 
 func RunErrorProne(ctx android.ModuleContext, srcFiles android.Paths, srcFileLists android.Paths,
@@ -199,22 +186,21 @@
 	return classFileList
 }
 
-func TransformClassesToJar(ctx android.ModuleContext, classes []jarSpec,
+func TransformResourcesToJar(ctx android.ModuleContext, resources []jarSpec,
 	manifest android.OptionalPath, deps android.Paths) android.Path {
 
-	outputFile := android.PathForModuleOut(ctx, "classes-full-debug.jar")
+	outputFile := android.PathForModuleOut(ctx, "res.jar")
 
 	jarArgs := []string{}
 
-	for _, j := range classes {
-		deps = append(deps, j.path())
-		jarArgs = append(jarArgs, j.jarArgs())
+	for _, j := range resources {
+		deps = append(deps, j.fileList)
+		jarArgs = append(jarArgs, j.soongJarArgs())
 	}
 
-	operation := "cf"
 	if manifest.Valid() {
-		operation = "cfm"
 		deps = append(deps, manifest.Path())
+		jarArgs = append(jarArgs, "-m "+manifest.String())
 	}
 
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
@@ -223,15 +209,31 @@
 		Output:      outputFile,
 		Implicits:   deps,
 		Args: map[string]string{
-			"jarArgs":   strings.Join(jarArgs, " "),
-			"operation": operation,
-			"manifest":  manifest.String(),
+			"jarArgs": strings.Join(jarArgs, " "),
 		},
 	})
 
 	return outputFile
 }
 
+func TransformJarsToJar(ctx android.ModuleContext, stem string, jars android.Paths) android.Path {
+
+	outputFile := android.PathForModuleOut(ctx, stem)
+
+	if len(jars) == 1 {
+		return jars[0]
+	}
+
+	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		Rule:        combineJar,
+		Description: "combine jars",
+		Output:      outputFile,
+		Inputs:      jars,
+	})
+
+	return outputFile
+}
+
 func TransformClassesJarToDex(ctx android.ModuleContext, classesJar android.Path,
 	flags javaBuilderFlags) jarSpec {
 
@@ -249,7 +251,7 @@
 		},
 	})
 
-	return jarSpec{outputFile}
+	return jarSpec{outputFile, outDir}
 }
 
 func TransformDexToJavaLib(ctx android.ModuleContext, resources []jarSpec,
@@ -260,12 +262,12 @@
 	var jarArgs []string
 
 	for _, j := range resources {
-		deps = append(deps, j.path())
-		jarArgs = append(jarArgs, j.jarArgs())
+		deps = append(deps, j.fileList)
+		jarArgs = append(jarArgs, j.soongJarArgs())
 	}
 
-	deps = append(deps, dexJarSpec.path())
-	jarArgs = append(jarArgs, dexJarSpec.jarArgs())
+	deps = append(deps, dexJarSpec.fileList)
+	jarArgs = append(jarArgs, dexJarSpec.soongJarArgs())
 
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 		Rule:        jar,
@@ -273,15 +275,14 @@
 		Output:      outputFile,
 		Implicits:   deps,
 		Args: map[string]string{
-			"operation": "cf",
-			"jarArgs":   strings.Join(jarArgs, " "),
+			"jarArgs": strings.Join(jarArgs, " "),
 		},
 	})
 
 	return outputFile
 }
 
-func TransformJarJar(ctx android.ModuleContext, classesJar android.Path, rulesFile android.Path) android.Path {
+func TransformJarJar(ctx android.ModuleContext, classesJar android.Path, rulesFile android.Path) android.ModuleOutPath {
 	outputFile := android.PathForModuleOut(ctx, "classes-jarjar.jar")
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 		Rule:        jarjar,
@@ -296,41 +297,3 @@
 
 	return outputFile
 }
-
-func TransformPrebuiltJarToClasses(ctx android.ModuleContext,
-	subdir string, prebuilt android.Path) (classJarSpec, resourceJarSpec jarSpec) {
-
-	classDir := android.PathForModuleOut(ctx, subdir, "classes")
-	classFileList := android.PathForModuleOut(ctx, subdir, "classes.list")
-	resourceFileList := android.PathForModuleOut(ctx, subdir, "resources.list")
-
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
-		Rule:        extractPrebuilt,
-		Description: "extract classes",
-		Outputs:     android.WritablePaths{classFileList, resourceFileList},
-		Input:       prebuilt,
-		Args: map[string]string{
-			"outDir":       classDir.String(),
-			"classFile":    classFileList.String(),
-			"resourceFile": resourceFileList.String(),
-		},
-	})
-
-	return jarSpec{classFileList}, jarSpec{resourceFileList}
-}
-
-func TransformFileListToJarSpec(ctx android.ModuleContext, dir, fileListFile android.Path) jarSpec {
-	outputFile := android.PathForModuleOut(ctx, fileListFile.Base()+".jarArgs")
-
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
-		Rule:        fileListToJarArgs,
-		Description: "file list to jar args",
-		Output:      outputFile,
-		Input:       fileListFile,
-		Args: map[string]string{
-			"outDir": dir.String(),
-		},
-	})
-
-	return jarSpec{outputFile}
-}
diff --git a/java/config/config.go b/java/config/config.go
index 047c4cb..cfedf3d 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -57,8 +57,9 @@
 	pctx.SourcePathVariable("JlinkCmd", "${JavaToolchain}/jlink")
 	pctx.SourcePathVariable("JmodCmd", "${JavaToolchain}/jmod")
 
-	pctx.StaticVariable("Zip2ZipCmd", filepath.Join("${bootstrap.ToolDir}", "zip2zip"))
 	pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
+	pctx.StaticVariable("SoongZipCmd", filepath.Join("${bootstrap.ToolDir}", "soong_zip"))
+	pctx.StaticVariable("MergeZipsCmd", filepath.Join("${bootstrap.ToolDir}", "merge_zips"))
 	pctx.HostBinToolVariable("DxCmd", "dx")
 	pctx.HostJavaToolVariable("JarjarCmd", "jarjar.jar")
 
diff --git a/java/java.go b/java/java.go
index 7b213b2..b76c2a4 100644
--- a/java/java.go
+++ b/java/java.go
@@ -134,12 +134,6 @@
 	// output file suitable for installing or running
 	outputFile android.Path
 
-	// jarSpecs suitable for inserting classes from a static library into another jar
-	classJarSpecs []jarSpec
-
-	// jarSpecs suitable for inserting resources from a static library into another jar
-	resourceJarSpecs []jarSpec
-
 	exportAidlIncludeDirs android.Paths
 
 	logtagsSrcs android.Paths
@@ -154,8 +148,6 @@
 
 type Dependency interface {
 	ClasspathFiles() android.Paths
-	ClassJarSpecs() []jarSpec
-	ResourceJarSpecs() []jarSpec
 	AidlIncludeDirs() android.Paths
 }
 
@@ -229,9 +221,8 @@
 	return flags
 }
 
-func (j *Module) collectDeps(ctx android.ModuleContext) (classpath android.Paths,
-	bootClasspath android.Paths, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess android.OptionalPath,
-	aidlIncludeDirs android.Paths, srcFileLists android.Paths) {
+func (j *Module) collectDeps(ctx android.ModuleContext) (classpath, bootClasspath, staticJars,
+	aidlIncludeDirs, srcFileLists android.Paths, aidlPreprocess android.OptionalPath) {
 
 	ctx.VisitDirectDeps(func(module blueprint.Module) {
 		otherName := ctx.OtherModuleName(module)
@@ -254,8 +245,7 @@
 			classpath = append(classpath, dep.ClasspathFiles()...)
 		case staticLibTag:
 			classpath = append(classpath, dep.ClasspathFiles()...)
-			classJarSpecs = append(classJarSpecs, dep.ClassJarSpecs()...)
-			resourceJarSpecs = append(resourceJarSpecs, dep.ResourceJarSpecs()...)
+			staticJars = append(staticJars, dep.ClasspathFiles()...)
 		case frameworkResTag:
 			if ctx.ModuleName() == "framework" {
 				// framework.jar has a one-off dependency on the R.java and Manifest.java files
@@ -280,16 +270,15 @@
 		aidlIncludeDirs = append(aidlIncludeDirs, dep.AidlIncludeDirs()...)
 	})
 
-	return classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
-		aidlIncludeDirs, srcFileLists
+	return
 }
 
 func (j *Module) compile(ctx android.ModuleContext) {
 
 	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Export_aidl_include_dirs)
 
-	classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
-		aidlIncludeDirs, srcFileLists := j.collectDeps(ctx)
+	classpath, bootClasspath, staticJars, aidlIncludeDirs, srcFileLists,
+		aidlPreprocess := j.collectDeps(ctx)
 
 	var flags javaBuilderFlags
 
@@ -341,6 +330,8 @@
 
 	var extraJarDeps android.Paths
 
+	var jars android.Paths
+
 	if len(srcFiles) > 0 {
 		// Compile java sources into .class files
 		classes := TransformJavaToClasses(ctx, srcFiles, srcFileLists, flags, deps)
@@ -359,37 +350,37 @@
 			extraJarDeps = append(extraJarDeps, errorprone)
 		}
 
-		classJarSpecs = append([]jarSpec{classes}, classJarSpecs...)
+		jars = append(jars, classes)
 	}
 
-	resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs, j.properties.Exclude_resource_dirs),
-		resourceJarSpecs...)
-
+	resourceJarSpecs := ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs, j.properties.Exclude_resource_dirs)
 	manifest := android.OptionalPathForModuleSrc(ctx, j.properties.Manifest)
 
-	allJarSpecs := append([]jarSpec(nil), classJarSpecs...)
-	allJarSpecs = append(allJarSpecs, resourceJarSpecs...)
-
-	// Combine classes + resources into classes-full-debug.jar
-	outputFile := TransformClassesToJar(ctx, allJarSpecs, manifest, extraJarDeps)
-	if ctx.Failed() {
-		return
-	}
-
-	if j.properties.Jarjar_rules != nil {
-		jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
-		// Transform classes-full-debug.jar into classes-jarjar.jar
-		outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
+	if len(resourceJarSpecs) > 0 || manifest.Valid() {
+		// Combine classes + resources into classes-full-debug.jar
+		resourceJar := TransformResourcesToJar(ctx, resourceJarSpecs, manifest, extraJarDeps)
 		if ctx.Failed() {
 			return
 		}
 
-		classes, _ := TransformPrebuiltJarToClasses(ctx, "jarjar_extracted", outputFile)
-		classJarSpecs = []jarSpec{classes}
+		jars = append(jars, resourceJar)
 	}
 
-	j.resourceJarSpecs = resourceJarSpecs
-	j.classJarSpecs = classJarSpecs
+	jars = append(jars, staticJars...)
+
+	// Combine the classes built from sources, any manifests, and any static libraries into
+	// classes-combined.jar.  If there is only one input jar this step will be skipped.
+	outputFile := TransformJarsToJar(ctx, "classes-combined.jar", jars)
+
+	if j.properties.Jarjar_rules != nil {
+		jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
+		// Transform classes-combined.jar into classes-jarjar.jar
+		outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
+		if ctx.Failed() {
+			return
+		}
+	}
+
 	j.classpathFile = outputFile
 
 	if j.deviceProperties.Dex && len(srcFiles) > 0 {
@@ -447,14 +438,6 @@
 	return android.Paths{j.classpathFile}
 }
 
-func (j *Module) ClassJarSpecs() []jarSpec {
-	return j.classJarSpecs
-}
-
-func (j *Module) ResourceJarSpecs() []jarSpec {
-	return j.resourceJarSpecs
-}
-
 func (j *Module) AidlIncludeDirs() android.Paths {
 	return j.exportAidlIncludeDirs
 }
@@ -580,9 +563,8 @@
 
 	properties ImportProperties
 
-	classpathFiles                  android.Paths
-	combinedClasspathFile           android.Path
-	classJarSpecs, resourceJarSpecs []jarSpec
+	classpathFiles        android.Paths
+	combinedClasspathFile android.Path
 }
 
 func (j *Import) Prebuilt() *android.Prebuilt {
@@ -603,14 +585,7 @@
 func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	j.classpathFiles = android.PathsForModuleSrc(ctx, j.properties.Jars)
 
-	for i, prebuilt := range j.classpathFiles {
-		subdir := "extracted" + strconv.Itoa(i)
-		classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, subdir, prebuilt)
-		j.classJarSpecs = append(j.classJarSpecs, classJarSpec)
-		j.resourceJarSpecs = append(j.resourceJarSpecs, resourceJarSpec)
-	}
-
-	j.combinedClasspathFile = TransformClassesToJar(ctx, j.classJarSpecs, android.OptionalPath{}, nil)
+	j.combinedClasspathFile = TransformJarsToJar(ctx, "classes.jar", j.classpathFiles)
 }
 
 var _ Dependency = (*Import)(nil)
@@ -619,14 +594,6 @@
 	return j.classpathFiles
 }
 
-func (j *Import) ClassJarSpecs() []jarSpec {
-	return j.classJarSpecs
-}
-
-func (j *Import) ResourceJarSpecs() []jarSpec {
-	return j.resourceJarSpecs
-}
-
 func (j *Import) AidlIncludeDirs() android.Paths {
 	return nil
 }
diff --git a/java/java_test.go b/java/java_test.go
index 6d9445b..4f5c0ec 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -69,6 +69,7 @@
 		bp += fmt.Sprintf(`
 			java_library {
 				name: "%s",
+				srcs: ["a.java"],
 				no_standard_libs: true,
 			}
 		`, extra)
@@ -112,20 +113,25 @@
 		`)
 
 	javac := ctx.ModuleForTests("foo", "").Rule("javac")
-	jar := ctx.ModuleForTests("foo", "").Rule("jar")
+	combineJar := ctx.ModuleForTests("foo", "").Rule("combineJar")
 
 	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
 		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
 	}
 
-	bar := filepath.Join(buildDir, ".intermediates", "bar", "classes-full-debug.jar")
+	bar := filepath.Join(buildDir, ".intermediates", "bar", "classes.jar")
+	baz := filepath.Join(buildDir, ".intermediates", "baz", "classes.jar")
+
 	if !strings.Contains(javac.Args["classpath"], bar) {
 		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bar)
 	}
 
-	baz := filepath.Join(buildDir, ".intermediates", "baz", "classes.list")
-	if !strings.Contains(jar.Args["jarArgs"], baz) {
-		t.Errorf("foo jarArgs %v does not contain %q", jar.Args["jarArgs"], baz)
+	if !strings.Contains(javac.Args["classpath"], baz) {
+		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], baz)
+	}
+
+	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
+		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
 	}
 }
 
@@ -176,7 +182,7 @@
 
 	check := func(module string, depType depType, deps ...string) {
 		for i := range deps {
-			deps[i] = filepath.Join(buildDir, ".intermediates", deps[i], "classes-full-debug.jar")
+			deps[i] = filepath.Join(buildDir, ".intermediates", deps[i], "classes.jar")
 		}
 		dep := strings.Join(deps, ":")
 
@@ -229,16 +235,15 @@
 		`)
 
 	javac := ctx.ModuleForTests("foo", "").Rule("javac")
-	jar := ctx.ModuleForTests("foo", "").Rule("jar")
+	combineJar := ctx.ModuleForTests("foo", "").Rule("combineJar")
 
 	bar := "a.jar"
 	if !strings.Contains(javac.Args["classpath"], bar) {
 		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bar)
 	}
 
-	baz := filepath.Join(buildDir, ".intermediates", "baz", "extracted0", "classes.list")
-	if !strings.Contains(jar.Args["jarArgs"], baz) {
-		t.Errorf("foo jarArgs %v does not contain %q", jar.Args["jarArgs"], baz)
+	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != "b.jar" {
+		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, "b.jar")
 	}
 }
 
@@ -268,20 +273,20 @@
 		`)
 
 	javac := ctx.ModuleForTests("foo", "").Rule("javac")
-	jar := ctx.ModuleForTests("foo", "").Rule("jar")
+	combineJar := ctx.ModuleForTests("foo", "").Rule("combineJar")
 
 	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
 		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
 	}
 
-	bar := filepath.Join(buildDir, ".intermediates", "bar", "classes-full-debug.jar")
+	bar := filepath.Join(buildDir, ".intermediates", "bar", "classes.jar")
 	if !strings.Contains(javac.Args["classpath"], bar) {
 		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bar)
 	}
 
-	baz := filepath.Join(buildDir, ".intermediates", "baz", "classes.list")
-	if !strings.Contains(jar.Args["jarArgs"], baz) {
-		t.Errorf("foo jarArgs %v does not contain %q", jar.Args["jarArgs"], baz)
+	baz := filepath.Join(buildDir, ".intermediates", "baz", "classes.jar")
+	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
+		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
 	}
 }
 
diff --git a/java/resources.go b/java/resources.go
index f1c9d06..60dc934 100644
--- a/java/resources.go
+++ b/java/resources.go
@@ -63,7 +63,7 @@
 
 			pattern := filepath.Join(dir.String(), "**/*")
 			bootstrap.GlobFile(ctx, pattern, excludes, fileListFile.String(), depFile)
-			jarSpecs = append(jarSpecs, TransformFileListToJarSpec(ctx, dir, fileListFile))
+			jarSpecs = append(jarSpecs, jarSpec{fileListFile, dir})
 		}
 	}