4141import java .util .concurrent .ScheduledThreadPoolExecutor ;
4242import java .util .concurrent .TimeUnit ;
4343import java .util .function .Function ;
44+ import java .util .function .Predicate ;
4445import java .util .function .Supplier ;
4546import java .util .regex .Pattern ;
4647
48+ import com .oracle .svm .agent .ignoredconfig .AgentMetaInfProcessor ;
4749import com .oracle .svm .agent .stackaccess .InterceptedState ;
4850import com .oracle .svm .agent .stackaccess .EagerlyLoadedJavaStackAccess ;
4951import com .oracle .svm .agent .stackaccess .OnDemandJavaStackAccess ;
5254import com .oracle .svm .agent .tracing .core .Tracer ;
5355import com .oracle .svm .agent .tracing .core .TracingResultWriter ;
5456import com .oracle .svm .core .configure .ConfigurationFile ;
57+ import com .oracle .svm .driver .metainf .NativeImageMetaInfWalker ;
58+ import org .graalvm .nativeimage .Platform ;
5559import org .graalvm .nativeimage .ProcessProperties ;
5660import org .graalvm .nativeimage .hosted .Feature ;
5761
@@ -104,12 +108,14 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
104108 String traceOutputFile = null ;
105109 String configOutputDir = null ;
106110 ConfigurationSet mergeConfigs = new ConfigurationSet ();
111+ ConfigurationSet omittedConfigs = new ConfigurationSet ();
107112 boolean builtinCallerFilter = true ;
108113 boolean builtinHeuristicFilter = true ;
109114 List <String > callerFilterFiles = new ArrayList <>();
110115 List <String > accessFilterFiles = new ArrayList <>();
111116 boolean experimentalClassLoaderSupport = true ;
112117 boolean experimentalClassDefineSupport = false ;
118+ boolean experimentalOmitClasspathConfig = false ;
113119 boolean build = false ;
114120 boolean configurationWithOrigins = false ;
115121 int configWritePeriod = -1 ; // in seconds
@@ -130,6 +136,14 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
130136 if (token .startsWith ("config-merge-dir=" )) {
131137 mergeConfigs .addDirectory (Paths .get (configOutputDir ));
132138 }
139+ } else if (token .startsWith ("config-to-omit=" )) {
140+ String omittedConfigDir = getTokenValue (token );
141+ omittedConfigDir = transformPath (omittedConfigDir );
142+ omittedConfigs .addDirectory (Paths .get (omittedConfigDir ));
143+ } else if (token .equals ("experimental-omit-config-from-classpath" )) {
144+ experimentalOmitClasspathConfig = true ;
145+ } else if (token .startsWith ("experimental-omit-config-from-classpath=" )) {
146+ experimentalOmitClasspathConfig = Boolean .parseBoolean (getTokenValue (token ));
133147 } else if (token .startsWith ("restrict-all-dir" ) || token .equals ("restrict" ) || token .startsWith ("restrict=" )) {
134148 warn ("restrict mode is no longer supported, ignoring option: " + token );
135149 } else if (token .equals ("no-builtin-caller-filter" )) {
@@ -235,7 +249,23 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
235249 }
236250 return e ; // rethrow
237251 };
252+ if (experimentalOmitClasspathConfig ) {
253+ ignoreConfigFromClasspath (jvmti , omittedConfigs );
254+ }
238255 AccessAdvisor advisor = createAccessAdvisor (builtinHeuristicFilter , callerFilter , accessFilter );
256+ TraceProcessor omittedConfigProcessor = null ;
257+ Predicate <String > shouldExcludeClassesWithHash = null ;
258+ if (!omittedConfigs .isEmpty ()) {
259+ Function <IOException , Exception > ignore = e -> {
260+ warn ("Failed to load omitted config: " + e );
261+ return null ;
262+ };
263+ omittedConfigProcessor = new TraceProcessor (advisor , omittedConfigs .loadJniConfig (ignore ), omittedConfigs .loadReflectConfig (ignore ),
264+ omittedConfigs .loadProxyConfig (ignore ), omittedConfigs .loadResourceConfig (ignore ), omittedConfigs .loadSerializationConfig (ignore ),
265+ omittedConfigs .loadPredefinedClassesConfig (null , null , ignore ), null );
266+ shouldExcludeClassesWithHash = omittedConfigProcessor .getPredefinedClassesConfiguration ()::containsClassWithHash ;
267+ }
268+
239269 Path [] predefinedClassDestinationDirs = {configOutputDirPath .resolve (ConfigurationFile .PREDEFINED_CLASSES_AGENT_EXTRACTED_SUBDIR )};
240270 if (configurationWithOrigins ) {
241271 ConfigurationWithOriginsResultWriter writer = new ConfigurationWithOriginsResultWriter (advisor , recordKeeper );
@@ -244,7 +274,7 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
244274 } else {
245275 TraceProcessor processor = new TraceProcessor (advisor , mergeConfigs .loadJniConfig (handler ), mergeConfigs .loadReflectConfig (handler ),
246276 mergeConfigs .loadProxyConfig (handler ), mergeConfigs .loadResourceConfig (handler ), mergeConfigs .loadSerializationConfig (handler ),
247- mergeConfigs .loadPredefinedClassesConfig (predefinedClassDestinationDirs , handler ));
277+ mergeConfigs .loadPredefinedClassesConfig (predefinedClassDestinationDirs , shouldExcludeClassesWithHash , handler ), omittedConfigProcessor );
248278 ConfigurationResultWriter writer = new ConfigurationResultWriter (processor );
249279 tracer = writer ;
250280 tracingResultWriter = writer ;
@@ -360,6 +390,30 @@ private void setupExecutorServiceForPeriodicConfigurationCapture(int writePeriod
360390 initialDelay , writePeriod , TimeUnit .SECONDS );
361391 }
362392
393+ private static void ignoreConfigFromClasspath (JvmtiEnv jvmti , ConfigurationSet ignoredConfigSet ) {
394+ String classpath = Support .getSystemProperty (jvmti , "java.class.path" );
395+ String sep = Support .getSystemProperty (jvmti , "path.separator" );
396+ if (sep == null ) {
397+ if (Platform .includedIn (Platform .LINUX .class ) || Platform .includedIn (Platform .DARWIN .class )) {
398+ sep = ":" ;
399+ } else if (Platform .includedIn (Platform .WINDOWS .class )) {
400+ sep = "[:;]" ;
401+ } else {
402+ warn ("Running on unknown platform. Not omitting existing config from classpath." );
403+ return ;
404+ }
405+ }
406+
407+ AgentMetaInfProcessor processor = new AgentMetaInfProcessor (ignoredConfigSet );
408+ for (String cpEntry : classpath .split (sep )) {
409+ try {
410+ NativeImageMetaInfWalker .walkMetaInfForCPEntry (Paths .get (cpEntry ), processor );
411+ } catch (NativeImageMetaInfWalker .MetaInfWalkException e ) {
412+ warn ("Failed to walk the classpath entry: " + cpEntry + " Reason: " + e );
413+ }
414+ }
415+ }
416+
363417 private static final Pattern propertyBlacklist = Pattern .compile ("(java\\ ..*)|(sun\\ ..*)|(jvmci\\ ..*)" );
364418 private static final Pattern propertyWhitelist = Pattern .compile ("(java\\ .library\\ .path)|(java\\ .io\\ .tmpdir)" );
365419
0 commit comments