Skip to content

Commit

Permalink
[GR-57308] Backport to 24.1: Emit an empty reachability-metadata.json…
Browse files Browse the repository at this point in the history
… file for helloworld

PullRequest: graal/18591
  • Loading branch information
loicottet authored and ansalond committed Aug 16, 2024
2 parents 863a272 + 6422961 commit c014e6a
Show file tree
Hide file tree
Showing 24 changed files with 240 additions and 187 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import java.io.IOException;
import java.io.Writer;
import java.nio.file.Path;

/**
* Subclass of {@link JsonWriter} that pretty-prints its output. More specifically, a newline will
Expand All @@ -42,6 +43,10 @@ public JsonPrettyWriter(Writer writer) {
super(writer);
}

public JsonPrettyWriter(Path path) throws IOException {
super(path);
}

@Override
public JsonWriter appendObjectStart() throws IOException {
return super.appendObjectStart().indent().newline();
Expand All @@ -53,6 +58,17 @@ public JsonWriter appendObjectEnd() throws IOException {
return super.appendObjectEnd();
}

@Override
public JsonWriter appendArrayStart() throws IOException {
return super.appendArrayStart().indent().newline();
}

@Override
public JsonWriter appendArrayEnd() throws IOException {
unindent().newline();
return super.appendArrayEnd();
}

@Override
public JsonWriter appendFieldSeparator() throws IOException {
return super.appendFieldSeparator().append(' ');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public interface JsonPrinter<T> {
* @see JsonWriter#print(Object)
*/
static <T> void printCollection(JsonWriter writer, Collection<T> collection, Comparator<T> comparator, JsonPrinter<T> elementPrinter) throws IOException {
if (collection.isEmpty()) {
writer.append("[]");
return;
}

Collection<T> ordered = collection;
if (comparator != null) {
ordered = new ArrayList<>(collection);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
import com.oracle.svm.configure.trace.AccessAdvisor;
import com.oracle.svm.configure.trace.TraceProcessor;
import com.oracle.svm.core.configure.ConfigurationFile;
import com.oracle.svm.core.configure.PredefinedClassesConfigurationParser;
import com.oracle.svm.core.jni.headers.JNIEnvironment;
import com.oracle.svm.core.jni.headers.JNIJavaVM;
import com.oracle.svm.core.jni.headers.JNIObjectHandle;
Expand All @@ -86,6 +87,8 @@
import com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEventCallbacks;
import com.oracle.svm.jvmtiagentbase.jvmti.JvmtiInterface;

import jdk.graal.compiler.phases.common.LazyValue;

public final class NativeImageAgent extends JvmtiAgentBase<NativeImageAgentJNIHandleSet> {
private static final String AGENT_NAME = "native-image-agent";
private static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("UTC");
Expand Down Expand Up @@ -338,7 +341,7 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
tracingResultWriter = new ConfigurationWithOriginsWriter(configWithOriginsTracer);
}
} else {
Path[] predefinedClassDestDirs = {Files.createDirectories(configOutputDirPath.resolve(ConfigurationFile.PREDEFINED_CLASSES_AGENT_EXTRACTED_SUBDIR))};
List<LazyValue<Path>> predefinedClassDestDirs = List.of(PredefinedClassesConfigurationParser.directorySupplier(configOutputDirPath));
Function<IOException, Exception> handler = e -> {
if (e instanceof NoSuchFileException) {
warn("file " + ((NoSuchFileException) e).getFile() + " for merging could not be found, skipping");
Expand Down Expand Up @@ -543,9 +546,11 @@ private void writeConfigurationFiles() {
throw unexpectedlyModified(configOutputLockFilePath);
}
expectUnmodified(configOutputLockFilePath);
if (!mostRecent.equals(expectedConfigModifiedBefore)) {
throw unexpectedlyModified(configOutputDirPath);
}
/*
* Checking for the modification of the whole configuration directory is not possible
* since predefined classes configuration outputs folders and files during the agent
* run.
*/

Path[] targetFilePaths = new Path[tempFilePaths.size()];
for (int i = 0; i < tempFilePaths.size(); i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@
import com.oracle.svm.configure.filters.HierarchyFilterNode;
import com.oracle.svm.configure.trace.AccessAdvisor;
import com.oracle.svm.configure.trace.TraceProcessor;
import com.oracle.svm.core.configure.ConfigurationFile;
import com.oracle.svm.core.configure.PredefinedClassesConfigurationParser;
import com.oracle.svm.util.LogUtils;

import jdk.graal.compiler.phases.common.LazyValue;

public class ConfigurationGenerateCommand extends ConfigurationCommand {
@Override
public String getName() {
Expand Down Expand Up @@ -264,14 +266,12 @@ protected static void generate(Iterator<String> argumentsIterator, boolean accep

try {
omittedConfigurationSet = omittedCollection.loadConfigurationSet(ConfigurationFileCollection.FAIL_ON_EXCEPTION, null, null);
List<Path> predefinedClassDestDirs = new ArrayList<>();
List<LazyValue<Path>> predefinedClassDestDirs = new ArrayList<>();
for (URI pathUri : outputCollection.getPredefinedClassesConfigPaths()) {
Path subdir = Files.createDirectories(Paths.get(pathUri).getParent().resolve(ConfigurationFile.PREDEFINED_CLASSES_AGENT_EXTRACTED_SUBDIR));
subdir = Files.createDirectories(subdir);
predefinedClassDestDirs.add(subdir);
predefinedClassDestDirs.add(PredefinedClassesConfigurationParser.directorySupplier(Paths.get(pathUri).getParent()));
}
Predicate<String> shouldExcludeClassesWithHash = omittedConfigurationSet.getPredefinedClassesConfiguration()::containsClassWithHash;
configurationSet = inputCollection.loadConfigurationSet(ConfigurationFileCollection.FAIL_ON_EXCEPTION, predefinedClassDestDirs.toArray(new Path[0]), shouldExcludeClassesWithHash);
configurationSet = inputCollection.loadConfigurationSet(ConfigurationFileCollection.FAIL_ON_EXCEPTION, predefinedClassDestDirs, shouldExcludeClassesWithHash);
} catch (IOException e) {
throw e;
} catch (Throwable t) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
final class ConfigurationConditionPrintable {
static void printConditionAttribute(UnresolvedConfigurationCondition condition, JsonWriter writer) throws IOException {
if (!condition.isAlwaysTrue()) {
writer.quote(CONDITIONAL_KEY).append(":{");
writer.quote(condition.isRuntimeChecked() ? TYPE_REACHED_KEY : TYPE_REACHABLE_KEY).append(':').quote(condition.getTypeName());
writer.append("},").newline();
writer.quote(CONDITIONAL_KEY).appendFieldSeparator().appendObjectStart();
writer.quote(condition.isRuntimeChecked() ? TYPE_REACHED_KEY : TYPE_REACHABLE_KEY).appendFieldSeparator().quote(condition.getTypeName());
writer.appendObjectEnd().appendSeparator();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
Expand All @@ -44,6 +45,7 @@
import com.oracle.svm.core.configure.ConfigurationFile;
import com.oracle.svm.core.configure.ConfigurationParser;
import com.oracle.svm.core.util.VMError;
import jdk.graal.compiler.phases.common.LazyValue;

public class ConfigurationFileCollection {
public static final Function<IOException, Exception> FAIL_ON_EXCEPTION = e -> e;
Expand Down Expand Up @@ -161,7 +163,7 @@ public ProxyConfiguration loadProxyConfig(Function<IOException, Exception> excep
return proxyConfiguration;
}

public PredefinedClassesConfiguration loadPredefinedClassesConfig(Path[] classDestinationDirs, Predicate<String> shouldExcludeClassesWithHash,
public PredefinedClassesConfiguration loadPredefinedClassesConfig(List<LazyValue<Path>> classDestinationDirs, Predicate<String> shouldExcludeClassesWithHash,
Function<IOException, Exception> exceptionHandler) throws Exception {
PredefinedClassesConfiguration predefinedClassesConfiguration = new PredefinedClassesConfiguration(classDestinationDirs, shouldExcludeClassesWithHash);
loadConfig(predefinedClassesConfigPaths, predefinedClassesConfiguration.createParser(false), exceptionHandler);
Expand All @@ -182,7 +184,7 @@ public SerializationConfiguration loadSerializationConfig(Function<IOException,
return serializationConfiguration;
}

public ConfigurationSet loadConfigurationSet(Function<IOException, Exception> exceptionHandler, Path[] predefinedConfigClassDestinationDirs,
public ConfigurationSet loadConfigurationSet(Function<IOException, Exception> exceptionHandler, List<LazyValue<Path>> predefinedConfigClassDestinationDirs,
Predicate<String> predefinedConfigClassWithHashExclusionPredicate) throws Exception {
return new ConfigurationSet(loadReflectConfig(exceptionHandler), loadJniConfig(exceptionHandler), loadResourceConfig(exceptionHandler), loadProxyConfig(exceptionHandler),
loadSerializationConfig(exceptionHandler),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package com.oracle.svm.configure.config;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -85,15 +86,10 @@ public boolean isConstructor() {

@Override
public void printJson(JsonWriter writer) throws IOException {
writer.append('{');
writer.quote("name").append(':').quote(name).append(',');
writer.quote("parameterTypes").append(":[");
String prefix = "";
for (String type : SignatureUtil.toParameterTypes(internalSignature)) {
writer.append(prefix).quote(type);
prefix = ",";
}
writer.append("] }");
writer.appendObjectStart();
writer.quote("name").appendFieldSeparator().quote(name).appendSeparator();
writer.quote("parameterTypes").appendFieldSeparator().print(Arrays.asList(SignatureUtil.toParameterTypes(internalSignature)));
writer.appendObjectEnd();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.oracle.svm.core.configure.ConfigurationFile;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.util.json.JsonPrettyWriter;
import jdk.graal.compiler.util.json.JsonPrintable;
import jdk.graal.compiler.util.json.JsonWriter;

Expand Down Expand Up @@ -71,9 +72,10 @@ public ConfigurationSet(ConfigurationSet other) {
other.predefinedClassesConfiguration.copy());
}

@SuppressWarnings("unchecked")
public ConfigurationSet() {
this(new TypeConfiguration(REFLECTION_KEY), new TypeConfiguration(JNI_KEY), new ResourceConfiguration(), new ProxyConfiguration(), new SerializationConfiguration(),
new PredefinedClassesConfiguration(new Path[0], hash -> false));
new PredefinedClassesConfiguration(Collections.emptyList(), hash -> false));
}

private ConfigurationSet mutate(ConfigurationSet other, Mutator mutator) {
Expand Down Expand Up @@ -161,8 +163,8 @@ public static List<Path> writeConfigurationToAllPaths(Function<ConfigurationFile
ConfigurationFile reachabilityMetadataFile = ConfigurationFile.REACHABILITY_METADATA;
for (Path path : configFilePathResolver.apply(reachabilityMetadataFile)) {
writtenFiles.add(path);
JsonWriter writer = new JsonWriter(path);
writer.appendObjectStart().indent().newline();
JsonWriter writer = new JsonPrettyWriter(path);
writer.appendObjectStart();
boolean first = true;
for (ConfigurationFile configFile : ConfigurationFile.agentGeneratedFiles()) {
JsonPrintable configuration = configSupplier.apply(configFile);
Expand All @@ -178,10 +180,14 @@ public static List<Path> writeConfigurationToAllPaths(Function<ConfigurationFile
}
}
} else {
if (configuration instanceof ConfigurationBase<?, ?> configurationBase && configurationBase.isEmpty()) {
/* Do not add an empty field when there are no entries */
continue;
}
if (first) {
first = false;
} else {
writer.appendSeparator().newline();
writer.appendSeparator();
}
if (!configFile.equals(ConfigurationFile.RESOURCES)) {
/*
Expand All @@ -193,7 +199,7 @@ public static List<Path> writeConfigurationToAllPaths(Function<ConfigurationFile
configSupplier.apply(configFile).printJson(writer);
}
}
writer.unindent().newline().appendObjectEnd();
writer.appendObjectEnd();
writer.close();
}
return writtenFiles;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,13 @@

import com.oracle.svm.configure.config.ConfigurationMemberInfo.ConfigurationMemberAccessibility;
import com.oracle.svm.configure.config.ConfigurationMemberInfo.ConfigurationMemberDeclaration;

import com.oracle.svm.core.configure.ConfigurationTypeDescriptor;

import jdk.graal.compiler.util.SignatureUtil;
import jdk.graal.compiler.util.json.JsonPrintable;
import jdk.graal.compiler.util.json.JsonPrinter;
import jdk.graal.compiler.util.json.JsonWriter;

import jdk.graal.compiler.util.SignatureUtil;

/**
* Type usage information, part of a {@link TypeConfiguration}. Unlike other configuration classes
* like {@link ConfigurationMethod}, this class is not immutable and uses locking to synchronize
Expand Down Expand Up @@ -461,9 +459,9 @@ public synchronized void setAllPublicConstructors(ConfigurationMemberAccessibili

@Override
public synchronized void printJson(JsonWriter writer) throws IOException {
writer.append('{').indent().newline();
writer.appendObjectStart();
ConfigurationConditionPrintable.printConditionAttribute(condition, writer);
writer.quote("type").append(":");
writer.quote("type").appendFieldSeparator();
typeDescriptor.printJson(writer);

printJsonBooleanIfSet(writer, allDeclaredFieldsAccess == ConfigurationMemberAccessibility.ACCESSED, "allDeclaredFields");
Expand All @@ -475,33 +473,33 @@ public synchronized void printJson(JsonWriter writer) throws IOException {
printJsonBooleanIfSet(writer, unsafeAllocated, "unsafeAllocated");

if (fields != null) {
writer.append(',').newline().quote("fields").append(':');
writer.appendSeparator().quote("fields").appendFieldSeparator();
JsonPrinter.printCollection(writer, fields.entrySet(), Map.Entry.comparingByKey(), ConfigurationType::printField);
}
if (methods != null) {
Set<ConfigurationMethod> accessedMethods = getMethodsByAccessibility(ConfigurationMemberAccessibility.ACCESSED);
if (!accessedMethods.isEmpty()) {
writer.append(',').newline().quote("methods").append(':');
writer.appendSeparator().quote("methods").appendFieldSeparator();
JsonPrinter.printCollection(writer,
accessedMethods,
Comparator.comparing(ConfigurationMethod::getName).thenComparing(Comparator.nullsFirst(Comparator.comparing(ConfigurationMethod::getInternalSignature))),
JsonPrintable::printJson);
}
}

writer.unindent().newline().append('}');
writer.appendObjectEnd();
}

private Set<ConfigurationMethod> getMethodsByAccessibility(ConfigurationMemberAccessibility accessibility) {
return methods.entrySet().stream().filter(e -> e.getValue().getAccessibility() == accessibility).map(Map.Entry::getKey).collect(Collectors.toSet());
}

private static void printField(Map.Entry<String, FieldInfo> entry, JsonWriter w) throws IOException {
w.append('{').quote("name").append(':').quote(entry.getKey());
w.appendObjectStart().quote("name").appendFieldSeparator().quote(entry.getKey());
if (entry.getValue().isFinalButWritable()) {
w.append(", ").quote("allowWrite").append(':').append("true");
w.appendSeparator().quote("allowWrite").appendFieldSeparator().append("true");
}
w.append('}');
w.appendObjectEnd();
}

private static void printJsonBooleanIfSet(JsonWriter writer, boolean predicate, String attribute) throws IOException {
Expand All @@ -511,7 +509,7 @@ private static void printJsonBooleanIfSet(JsonWriter writer, boolean predicate,
}

private static void printJsonBoolean(JsonWriter writer, boolean value, String attribute) throws IOException {
writer.append(',').newline().quote(attribute).append(":").append(Boolean.toString(value));
writer.appendSeparator().quote(attribute).appendFieldSeparator().append(Boolean.toString(value));
}

private void removeFields(ConfigurationMemberDeclaration declaration, ConfigurationMemberAccessibility accessibility) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import jdk.graal.compiler.phases.common.LazyValue;
import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition;

import com.oracle.svm.configure.ConfigurationBase;
Expand All @@ -46,11 +48,11 @@
import jdk.graal.compiler.util.json.JsonWriter;

public final class PredefinedClassesConfiguration extends ConfigurationBase<PredefinedClassesConfiguration, PredefinedClassesConfiguration.Predicate> {
private final Path[] classDestinationDirs;
private final List<LazyValue<Path>> classDestinationDirs;
private final ConcurrentMap<String, ConfigurationPredefinedClass> classes = new ConcurrentHashMap<>();
private final java.util.function.Predicate<String> shouldExcludeClassWithHash;

public PredefinedClassesConfiguration(Path[] classDestinationDirs, java.util.function.Predicate<String> shouldExcludeClassWithHash) {
public PredefinedClassesConfiguration(List<LazyValue<Path>> classDestinationDirs, java.util.function.Predicate<String> shouldExcludeClassWithHash) {
this.classDestinationDirs = classDestinationDirs;
this.shouldExcludeClassWithHash = shouldExcludeClassWithHash;
}
Expand Down Expand Up @@ -98,9 +100,9 @@ public void add(String nameInfo, byte[] classData) {
return;
}
if (classDestinationDirs != null) {
for (Path dir : classDestinationDirs) {
for (LazyValue<Path> dir : classDestinationDirs) {
try {
Files.write(dir.resolve(getFileName(hash)), classData);
Files.write(dir.get().resolve(getFileName(hash)), classData);
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand All @@ -121,11 +123,11 @@ public void add(String nameInfo, String hash, URI baseUri) {
} catch (Exception ignored) {
localBaseDir = null;
}
for (Path destDir : classDestinationDirs) {
if (!destDir.equals(localBaseDir)) {
for (LazyValue<Path> destDir : classDestinationDirs) {
if (!destDir.get().equals(localBaseDir)) {
try {
String fileName = getFileName(hash);
Path target = destDir.resolve(fileName);
Path target = destDir.get().resolve(fileName);
if (baseUri != null) {
try (InputStream is = PredefinedClassesConfigurationParser.openClassdataStream(baseUri, hash)) {
Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
Expand Down
Loading

0 comments on commit c014e6a

Please sign in to comment.