Skip to content

Commit

Permalink
[GR-30201] Introduce a native-image-agent and native-image-configure …
Browse files Browse the repository at this point in the history
…option to ignore previous configuration.

PullRequest: graal/8563
  • Loading branch information
Aleksandar Gradinac committed Jun 23, 2021
2 parents cf65f54 + a987c14 commit a461aa0
Show file tree
Hide file tree
Showing 35 changed files with 1,260 additions and 166 deletions.
5 changes: 3 additions & 2 deletions substratevm/mx.substratevm/mx_substratevm.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ def _native_unittest(native_image, cmdline_args):
except IOError:
mx.log('warning: could not read blacklist: ' + blacklist)

unittest_args = unmask(pargs.unittest_args) if unmask(pargs.unittest_args) else ['com.oracle.svm.test']
unittest_args = unmask(pargs.unittest_args) if unmask(pargs.unittest_args) else ['com.oracle.svm.test', 'com.oracle.svm.configure.test']
_native_junit(native_image, unittest_args, unmask(pargs.build_args), unmask(pargs.run_args), blacklist, whitelist, pargs.preserve_image)


Expand Down Expand Up @@ -848,7 +848,8 @@ def _native_image_launcher_extra_jvm_args():
'substratevm:SVM_AGENT',
],
build_args=[
'--features=com.oracle.svm.agent.NativeImageAgent$RegistrationFeature'
'--features=com.oracle.svm.agent.NativeImageAgent$RegistrationFeature',
'--enable-url-protocols=jar',
],
),
mx_sdk_vm.LibraryConfig(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Pattern;

import com.oracle.svm.agent.ignoredconfig.AgentMetaInfProcessor;
import com.oracle.svm.agent.stackaccess.InterceptedState;
import com.oracle.svm.agent.stackaccess.EagerlyLoadedJavaStackAccess;
import com.oracle.svm.agent.stackaccess.OnDemandJavaStackAccess;
Expand All @@ -52,6 +54,8 @@
import com.oracle.svm.agent.tracing.core.Tracer;
import com.oracle.svm.agent.tracing.core.TracingResultWriter;
import com.oracle.svm.core.configure.ConfigurationFile;
import com.oracle.svm.driver.metainf.NativeImageMetaInfWalker;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.ProcessProperties;
import org.graalvm.nativeimage.hosted.Feature;

Expand Down Expand Up @@ -104,12 +108,14 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
String traceOutputFile = null;
String configOutputDir = null;
ConfigurationSet mergeConfigs = new ConfigurationSet();
ConfigurationSet omittedConfigs = new ConfigurationSet();
boolean builtinCallerFilter = true;
boolean builtinHeuristicFilter = true;
List<String> callerFilterFiles = new ArrayList<>();
List<String> accessFilterFiles = new ArrayList<>();
boolean experimentalClassLoaderSupport = true;
boolean experimentalClassDefineSupport = false;
boolean experimentalOmitClasspathConfig = false;
boolean build = false;
boolean configurationWithOrigins = false;
int configWritePeriod = -1; // in seconds
Expand All @@ -130,6 +136,14 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
if (token.startsWith("config-merge-dir=")) {
mergeConfigs.addDirectory(Paths.get(configOutputDir));
}
} else if (token.startsWith("config-to-omit=")) {
String omittedConfigDir = getTokenValue(token);
omittedConfigDir = transformPath(omittedConfigDir);
omittedConfigs.addDirectory(Paths.get(omittedConfigDir));
} else if (token.equals("experimental-omit-config-from-classpath")) {
experimentalOmitClasspathConfig = true;
} else if (token.startsWith("experimental-omit-config-from-classpath=")) {
experimentalOmitClasspathConfig = Boolean.parseBoolean(getTokenValue(token));
} else if (token.startsWith("restrict-all-dir") || token.equals("restrict") || token.startsWith("restrict=")) {
warn("restrict mode is no longer supported, ignoring option: " + token);
} else if (token.equals("no-builtin-caller-filter")) {
Expand Down Expand Up @@ -235,7 +249,23 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
}
return e; // rethrow
};
if (experimentalOmitClasspathConfig) {
ignoreConfigFromClasspath(jvmti, omittedConfigs);
}
AccessAdvisor advisor = createAccessAdvisor(builtinHeuristicFilter, callerFilter, accessFilter);
TraceProcessor omittedConfigProcessor = null;
Predicate<String> shouldExcludeClassesWithHash = null;
if (!omittedConfigs.isEmpty()) {
Function<IOException, Exception> ignore = e -> {
warn("Failed to load omitted config: " + e);
return null;
};
omittedConfigProcessor = new TraceProcessor(advisor, omittedConfigs.loadJniConfig(ignore), omittedConfigs.loadReflectConfig(ignore),
omittedConfigs.loadProxyConfig(ignore), omittedConfigs.loadResourceConfig(ignore), omittedConfigs.loadSerializationConfig(ignore),
omittedConfigs.loadPredefinedClassesConfig(null, null, ignore), null);
shouldExcludeClassesWithHash = omittedConfigProcessor.getPredefinedClassesConfiguration()::containsClassWithHash;
}

Path[] predefinedClassDestinationDirs = {configOutputDirPath.resolve(ConfigurationFile.PREDEFINED_CLASSES_AGENT_EXTRACTED_SUBDIR)};
if (configurationWithOrigins) {
ConfigurationWithOriginsResultWriter writer = new ConfigurationWithOriginsResultWriter(advisor, recordKeeper);
Expand All @@ -244,7 +274,7 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
} else {
TraceProcessor processor = new TraceProcessor(advisor, mergeConfigs.loadJniConfig(handler), mergeConfigs.loadReflectConfig(handler),
mergeConfigs.loadProxyConfig(handler), mergeConfigs.loadResourceConfig(handler), mergeConfigs.loadSerializationConfig(handler),
mergeConfigs.loadPredefinedClassesConfig(predefinedClassDestinationDirs, handler));
mergeConfigs.loadPredefinedClassesConfig(predefinedClassDestinationDirs, shouldExcludeClassesWithHash, handler), omittedConfigProcessor);
ConfigurationResultWriter writer = new ConfigurationResultWriter(processor);
tracer = writer;
tracingResultWriter = writer;
Expand Down Expand Up @@ -360,6 +390,30 @@ private void setupExecutorServiceForPeriodicConfigurationCapture(int writePeriod
initialDelay, writePeriod, TimeUnit.SECONDS);
}

private static void ignoreConfigFromClasspath(JvmtiEnv jvmti, ConfigurationSet ignoredConfigSet) {
String classpath = Support.getSystemProperty(jvmti, "java.class.path");
String sep = Support.getSystemProperty(jvmti, "path.separator");
if (sep == null) {
if (Platform.includedIn(Platform.LINUX.class) || Platform.includedIn(Platform.DARWIN.class)) {
sep = ":";
} else if (Platform.includedIn(Platform.WINDOWS.class)) {
sep = "[:;]";
} else {
warn("Running on unknown platform. Not omitting existing config from classpath.");
return;
}
}

AgentMetaInfProcessor processor = new AgentMetaInfProcessor(ignoredConfigSet);
for (String cpEntry : classpath.split(sep)) {
try {
NativeImageMetaInfWalker.walkMetaInfForCPEntry(Paths.get(cpEntry), processor);
} catch (NativeImageMetaInfWalker.MetaInfWalkException e) {
warn("Failed to walk the classpath entry: " + cpEntry + " Reason: " + e);
}
}
}

private static final Pattern propertyBlacklist = Pattern.compile("(java\\..*)|(sun\\..*)|(jvmci\\..*)");
private static final Pattern propertyWhitelist = Pattern.compile("(java\\.library\\.path)|(java\\.io\\.tmpdir)");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.agent.ignoredconfig;

import java.nio.file.Path;

import com.oracle.svm.configure.config.ConfigurationSet;
import com.oracle.svm.driver.metainf.MetaInfFileType;
import com.oracle.svm.driver.metainf.NativeImageMetaInfResourceProcessor;

public class AgentMetaInfProcessor implements NativeImageMetaInfResourceProcessor {

private ConfigurationSet ignoredConfigSet;

public AgentMetaInfProcessor(ConfigurationSet ignoredConfigSet) {
this.ignoredConfigSet = ignoredConfigSet;
}

@Override
public void processMetaInfResource(Path classpathEntry, Path resourceRoot, Path resourcePath, MetaInfFileType type) throws Exception {
ignoredConfigSet.addDirectory(resourcePath.getParent());
}

@Override
public void showWarning(String message) {
}

@Override
public void showVerboseMessage(String message) {
}

@Override
public boolean isExcluded(Path resourcePath, Path classpathEntry) {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ private TraceProcessor createNewTraceProcessor() {
ProxyConfiguration proxyConfig = new ProxyConfiguration();
ResourceConfiguration resourceConfig = new ResourceConfiguration();
SerializationConfiguration serializationConfiguration = new SerializationConfiguration();
PredefinedClassesConfiguration predefinedClassesConfiguration = new PredefinedClassesConfiguration(new Path[0]);
return new TraceProcessor(advisor, jniConfig, reflectConfig, proxyConfig, resourceConfig, serializationConfiguration, predefinedClassesConfiguration);
PredefinedClassesConfiguration predefinedClassesConfiguration = new PredefinedClassesConfiguration(new Path[0], null);
return new TraceProcessor(advisor, jniConfig, reflectConfig, proxyConfig, resourceConfig, serializationConfiguration, predefinedClassesConfiguration, null);
}

private static final class MethodCallNode {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Args = -H:IncludeResources=com/oracle/svm/configure/test/config/.*json
Loading

0 comments on commit a461aa0

Please sign in to comment.