Add initial support for CDS images
PiperOrigin-RevId: 295770802
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
index 1e7cf52..2f6eb60 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
@@ -650,7 +650,8 @@
boolean usingNativeSinglejar,
// Explicitly ignoring params since Bazel doesn't yet support one version
OneVersionEnforcementLevel oneVersionEnforcementLevel,
- Artifact oneVersionWhitelistArtifact) {
+ Artifact oneVersionWhitelistArtifact,
+ Artifact sharedArchive) {
return DeployArchiveBuilder.defaultSingleJarCommandLineWithoutOneVersion(
output,
mainClass,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java
index 281b5a6..25b84a5 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java
@@ -69,6 +69,7 @@
private boolean checkDesugarDeps;
private OneVersionEnforcementLevel oneVersionEnforcementLevel = OneVersionEnforcementLevel.OFF;
@Nullable private Artifact oneVersionWhitelistArtifact;
+ @Nullable private Artifact sharedArchive;
/** Type of compression to apply to output archive. */
public enum Compression {
@@ -169,6 +170,11 @@
return this;
}
+ public DeployArchiveBuilder setSharedArchive(@Nullable Artifact sharedArchive) {
+ this.sharedArchive = sharedArchive;
+ return this;
+ }
+
public static CustomCommandLine.Builder defaultSingleJarCommandLineWithoutOneVersion(
Artifact outputJar,
String javaMainClass,
@@ -334,6 +340,9 @@
}
inputs.add(oneVersionWhitelistArtifact);
}
+ if (sharedArchive != null) {
+ inputs.add(sharedArchive);
+ }
// If singlejar's name ends with .jar, it is Java application, otherwise it is native.
// TODO(asmundak): once https://github.com/bazelbuild/bazel/issues/2241 is fixed (that is,
// the native singlejar is used on windows) remove support for the Java implementation
@@ -355,7 +364,8 @@
launcher,
usingNativeSinglejar,
oneVersionEnforcementLevel,
- oneVersionWhitelistArtifact);
+ oneVersionWhitelistArtifact,
+ sharedArchive);
if (checkDesugarDeps) {
commandLine = CommandLine.concat(commandLine, ImmutableList.of("--check_desugar_deps"));
}
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 0be02b5..e51444d 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,6 +22,8 @@
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;
@@ -31,8 +33,11 @@
import com.google.devtools.build.lib.analysis.RunfilesProvider;
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;
import com.google.devtools.build.lib.analysis.config.CompilationMode;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.cmdline.Label;
@@ -368,6 +373,8 @@
ImmutableList<String> deployManifestLines =
getDeployManifestLines(ruleContext, originalMainClass);
+ Artifact jsa = createSharedArchive(ruleContext, javaArtifacts, attributes);
+
deployArchiveBuilder
.setOutputJar(deployJar)
.setJavaStartClass(mainClass)
@@ -382,6 +389,7 @@
.setOneVersionEnforcementLevel(
javaConfig.oneVersionEnforcementLevel(),
JavaToolchainProvider.from(ruleContext).getOneVersionWhitelist())
+ .setSharedArchive(jsa)
.build();
Artifact unstrippedDeployJar =
@@ -493,10 +501,52 @@
.build();
}
+ private static Artifact createSharedArchive(
+ RuleContext ruleContext,
+ JavaCompilationArtifacts javaArtifacts,
+ JavaTargetAttributes attributes)
+ throws InterruptedException {
+ if (!ruleContext.getRule().isAttrDefined("classlist", BuildType.LABEL)) {
+ return null;
+ }
+ Artifact classlist = ruleContext.getPrerequisiteArtifact("classlist", Mode.HOST);
+ if (classlist == null) {
+ return null;
+ }
+ NestedSet<Artifact> classpath =
+ NestedSetBuilder.<Artifact>stableOrder()
+ .addAll(javaArtifacts.getRuntimeJars())
+ .addTransitive(attributes.getRuntimeClassPathForArchive())
+ .build();
+ Artifact jsa = ruleContext.getImplicitOutputArtifact(JavaSemantics.SHARED_ARCHIVE_ARTIFACT);
+ JavaRuntimeInfo javaRuntime = JavaRuntimeInfo.from(ruleContext);
+ ruleContext.registerAction(
+ new SpawnAction.Builder()
+ .setExecutable(javaRuntime.javaBinaryExecPathFragment())
+ .addCommandLine(
+ CustomCommandLine.builder()
+ .add("-Xshare:dump")
+ .addFormatted("-XX:SharedArchiveFile=%s", jsa.getExecPath())
+ .addFormatted("-XX:SharedClassListFile=%s", classlist.getExecPath())
+ .add("-cp")
+ .build())
+ .addCommandLine(
+ CustomCommandLine.builder()
+ .addExecPaths(VectorArg.join(":").each(classpath))
+ .build(),
+ ParamFileInfo.builder(ParameterFileType.UNQUOTED).build())
+ .addOutput(jsa)
+ .addInput(classlist)
+ .addTransitiveInputs(javaRuntime.javaBaseInputsMiddleman())
+ .addTransitiveInputs(classpath)
+ .build(ruleContext));
+ return jsa;
+ }
+
// Create the deploy jar and make it dependent on the runfiles middleman if an executable is
// created. Do not add the deploy jar to files to build, so we will only build it when it gets
// requested.
- private ImmutableList<String> getDeployManifestLines(
+ private static ImmutableList<String> getDeployManifestLines(
RuleContext ruleContext, String originalMainClass) {
ImmutableList.Builder<String> builder =
ImmutableList.<String>builder()
@@ -508,7 +558,7 @@
}
/** Add Java8 timezone resource jar to java binary, if specified in tool chain. */
- private void addTimezoneResourceForJavaBinaries(
+ private static void addTimezoneResourceForJavaBinaries(
RuleContext ruleContext, JavaTargetAttributes.Builder attributesBuilder) {
JavaToolchainProvider toolchainProvider = JavaToolchainProvider.from(ruleContext);
if (toolchainProvider.getTimezoneData() != null) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java
index 0466a13..181aae6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java
@@ -78,6 +78,7 @@
SafeImplicitOutputsFunction JAVA_BINARY_PROGUARD_CONFIG =
fromTemplates("%{name}_proguard.config");
SafeImplicitOutputsFunction JAVA_ONE_VERSION_ARTIFACT = fromTemplates("%{name}-one-version.txt");
+ SafeImplicitOutputsFunction SHARED_ARCHIVE_ARTIFACT = fromTemplates("%{name}.jsa");
SafeImplicitOutputsFunction JAVA_COVERAGE_RUNTIME_CLASS_PATH_TXT =
fromTemplates("%{name}-runtime-classpath.txt");
@@ -263,7 +264,8 @@
Artifact launcher,
boolean usingNativeSinglejar,
OneVersionEnforcementLevel oneVersionEnforcementLevel,
- Artifact oneVersionWhitelistArtifact);
+ Artifact oneVersionWhitelistArtifact,
+ Artifact sharedArchive);
/**
* Creates the action that writes the Java executable stub script.