From ca0771fecd5eb0f22fc4b91ccaa9a4d646aca5c1 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 14 Jun 2023 09:32:40 +0200 Subject: [PATCH 1/7] svm: better error message if preview features are not enabled but required by the class file --- .../svm/hosted/NativeImageGeneratorRunner.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index cb11c46b468d..473223a5a667 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -434,11 +434,15 @@ private int buildImage(ImageClassLoader classLoader) { } catch (ClassNotFoundException ex) { throw UserError.abort(classLoader.getMainClassNotFoundErrorMessage(className)); } catch (UnsupportedClassVersionError ex) { - throw UserError.abort("Unable to load '%s' due to a Java version mismatch.%n" + - "Please take one of the following actions:%n" + - " 1) Recompile the source files for your application using Java %s, then try running native-image again%n" + - " 2) Use a version of native-image corresponding to the version of Java with which you compiled the source files for your application%n", - className, Runtime.version().feature()); + if (ex.getMessage().startsWith("Preview features are not enabled")) { + throw UserError.abort(ex.getMessage()); + } else { + throw UserError.abort("Unable to load '%s' due to a Java version mismatch.%n" + + "Please take one of the following actions:%n" + + " 1) Recompile the source files for your application using Java %s, then try running native-image again%n" + + " 2) Use a version of native-image corresponding to the version of Java with which you compiled the source files for your application%n", + className, Runtime.version().feature()); + } } String mainEntryPointName = SubstrateOptions.Method.getValue(parsedHostedOptions); if (mainEntryPointName.isEmpty()) { From fc73a48052f6842fa05b93afb1b1d990593b1215 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 14 Jun 2023 13:07:31 +0200 Subject: [PATCH 2/7] svm: mx helloworld now supports different variants [GR-46507] --- substratevm/mx.substratevm/mx_substratevm.py | 56 ++++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 865d7e725e08..381ec8a71f94 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -55,6 +55,7 @@ import sys + if sys.version_info[0] < 3: from StringIO import StringIO else: @@ -730,13 +731,54 @@ def _cinterfacetutorial(native_image, args=None): mx.run([join(build_dir, 'cinterfacetutorial')]) -def _helloworld(native_image, javac_command, path, build_only, args): +_helloworld_variants = { + 'traditional': ''' +public class HelloWorld { + public static void main(String[] args) { + System.out.println(System.getenv("%s")); + } +} +''', + 'noArgs': ''' +// requires JDK 21 and --enable-preview +public class HelloWorld { + static void main() { + System.out.println(System.getenv("%s")); + } +} +''', + 'instance': ''' +// requires JDK 21 and --enable-preview +class HelloWorld { + void main(String[] args) { + System.out.println(System.getenv("%s")); + } +} +''', + 'instanceNoArgs': ''' +// requires JDK 21 and --enable-preview +class HelloWorld { + void main() { + System.out.println(System.getenv("%s")); + } +} +''', + 'unnamedClass': ''' +// requires JDK 21 and javac --enable-preview --source 21 and native-image --enable-preview +void main() { + System.out.println(System.getenv("%s")); +} +''', +} + + +def _helloworld(native_image, javac_command, path, build_only, args, variant=list(_helloworld_variants.keys())[0]): mkpath(path) hello_file = os.path.join(path, 'HelloWorld.java') envkey = 'HELLO_WORLD_MESSAGE' output = 'Hello from native-image!' with open(hello_file, 'w') as fp: - fp.write('public class HelloWorld { public static void main(String[] args) { System.out.println(System.getenv("' + envkey + '")); } }') + fp.write(_helloworld_variants[variant] % envkey) fp.flush() mx.run(javac_command + [hello_file]) @@ -1238,20 +1280,26 @@ def _native_image_configure_extra_jvm_args(): def run_helloworld_command(args, config, command_name): parser = ArgumentParser(prog='mx ' + command_name) - all_args = ['--output-path', '--javac-command', '--build-only'] + all_args = ['--output-path', '--javac-command', '--build-only', '--variant', '--list'] masked_args = [_mask(arg, all_args) for arg in args] + default_variant = list(_helloworld_variants.keys())[0] parser.add_argument(all_args[0], metavar='', nargs=1, help='Path of the generated image', default=[svmbuild_dir(suite)]) parser.add_argument(all_args[1], metavar='', help='A javac command to be used', default=mx.get_jdk().javac) parser.add_argument(all_args[2], action='store_true', help='Only build the native image') + parser.add_argument(all_args[3], choices=_helloworld_variants.keys(), default=default_variant, help=f'The Hello World source code variant to use (default: {default_variant})') + parser.add_argument(all_args[4], action='store_true', help='Print the Hello World source and exit') parser.add_argument('image_args', nargs='*', default=[]) parsed = parser.parse_args(masked_args) javac_command = unmask(parsed.javac_command.split()) output_path = unmask(parsed.output_path)[0] build_only = parsed.build_only image_args = unmask(parsed.image_args) + if parsed.list: + mx.log(_helloworld_variants[parsed.variant]) + return native_image_context_run( lambda native_image, a: - _helloworld(native_image, javac_command, output_path, build_only, a), unmask(image_args), + _helloworld(native_image, javac_command, output_path, build_only, a, variant=parsed.variant), unmask(image_args), config=config, ) From 9265c7cc16ceeac8eb30572f57e81b7ba1d8db5d Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 12 Jun 2023 17:03:31 +0200 Subject: [PATCH 3/7] svm: support instance main methods (JEP 445) [GR-46507] --- .../com/oracle/svm/core/JavaMainWrapper.java | 74 ++++++++++++++++++- .../hosted/NativeImageGeneratorRunner.java | 48 +++++++++--- 2 files changed, 109 insertions(+), 13 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java index 78794d2a7995..2ef312e8ed3d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java @@ -26,13 +26,16 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.function.BooleanSupplier; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.ImageSingletons; @@ -74,7 +77,9 @@ import com.oracle.svm.core.thread.ThreadListenerSupport; import com.oracle.svm.core.thread.VMThreads; import com.oracle.svm.core.util.CounterSupport; +import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; +import com.oracle.svm.util.ReflectionUtil; @InternalVMMethod public class JavaMainWrapper { @@ -92,14 +97,41 @@ public class JavaMainWrapper { public static class JavaMainSupport { - public final MethodHandle javaMainHandle; + private final MethodHandle javaMainHandle; + private final MethodHandle javaMainClassCtorHandle; final String javaMainClassName; public String[] mainArgs; + private final boolean mainWithoutArgs; + private final boolean mainNonstatic; + @Platforms(Platform.HOSTED_ONLY.class) public JavaMainSupport(Method javaMainMethod) throws IllegalAccessException { - this.javaMainHandle = MethodHandles.lookup().unreflect(javaMainMethod); + if (instanceMainMethodSupported()) { + javaMainMethod.setAccessible(true); + int mods = javaMainMethod.getModifiers(); + this.mainNonstatic = !Modifier.isStatic(mods); + this.mainWithoutArgs = javaMainMethod.getParameterCount() == 0; + MethodHandle mainHandle = MethodHandles.lookup().unreflect(javaMainMethod); + MethodHandle ctorHandle = null; + if (mainNonstatic) { + // Instance main + try { + Constructor ctor = ReflectionUtil.lookupConstructor(javaMainMethod.getDeclaringClass()); + ctorHandle = MethodHandles.lookup().unreflectConstructor(ctor); + } catch (ReflectionUtil.ReflectionUtilError ex) { + throw UserError.abort(ex, "no non-private zero argument constructor found in class %s", javaMainMethod.getDeclaringClass().getSimpleName()); + } + } + this.javaMainHandle = mainHandle; + this.javaMainClassCtorHandle = ctorHandle; + } else { + this.mainNonstatic = false; + this.mainWithoutArgs = false; + this.javaMainHandle = MethodHandles.lookup().unreflect(javaMainMethod); + this.javaMainClassCtorHandle = null; + } this.javaMainClassName = javaMainMethod.getDeclaringClass().getName(); } @@ -129,6 +161,42 @@ public List getInputArguments() { } return Collections.emptyList(); } + + } + + public static void invokeMain(String[] args) throws Throwable { + // This needs to be a local and not a parameter to allow proper constant folding + JavaMainSupport javaMainSupport = ImageSingletons.lookup(JavaMainSupport.class); + if (javaMainSupport.mainNonstatic) { + Object instance = javaMainSupport.javaMainClassCtorHandle.invoke(); + if (javaMainSupport.mainWithoutArgs) { + javaMainSupport.javaMainHandle.invoke(instance); + } else { + javaMainSupport.javaMainHandle.invoke(instance, args); + } + } else { + if (javaMainSupport.mainWithoutArgs) { + javaMainSupport.javaMainHandle.invokeExact(); + } else { + javaMainSupport.javaMainHandle.invokeExact(args); + } + } + } + + /** + * Determines whether instance main methodes are enabled. See JDK-8306112: Implementation of JEP + * 445: Unnamed Classes and Instance Main Methods (Preview). + */ + public static boolean instanceMainMethodSupported() { + if (JavaVersionUtil.JAVA_SPEC < 21) { + return false; + } + var previewFeature = ReflectionUtil.lookupClass(true, "jdk.internal.misc.PreviewFeatures"); + try { + return previewFeature != null && (Boolean) previewFeature.getDeclaredMethod("isEnabled").invoke(null); + } catch (ReflectiveOperationException e) { + throw VMError.shouldNotReachHere(e); + } } @Uninterruptible(reason = "The caller initialized the thread state, so the callees do not need to be uninterruptible.", calleeMustBe = false) @@ -175,7 +243,7 @@ private static int runCore0() { * exceptions in a InvocationTargetException. */ JavaMainSupport mainSupport = ImageSingletons.lookup(JavaMainSupport.class); - mainSupport.javaMainHandle.invokeExact(mainSupport.mainArgs); + invokeMain(mainSupport.mainArgs); return 0; } catch (Throwable ex) { JavaThreads.dispatchUncaughtException(Thread.currentThread(), ex); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index 473223a5a667..b3a5af28b156 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -26,6 +26,7 @@ import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.file.Files; @@ -456,12 +457,44 @@ private int buildImage(ImageClassLoader classLoader) { mainEntryPoint = mainClass.getDeclaredMethod(mainEntryPointName, int.class, CCharPointerPointer.class); } catch (NoSuchMethodException ignored2) { Method javaMainMethod; - try { /* * If no C-level main method was found, look for a Java-level main * method and use our wrapper to invoke it. */ - javaMainMethod = ReflectionUtil.lookupMethod(mainClass, mainEntryPointName, String[].class); + if ("main".equals(mainEntryPointName) && JavaMainWrapper.instanceMainMethodSupported()) { + // Instance main method only supported for "main" method name + try { + /* + * JDK-8306112: Implementation of JEP 445: Unnamed Classes and + * Instance Main Methods (Preview) + * + * MainMethodFinder will perform all the necessary checks + */ + Class mainMethodFinder = ReflectionUtil.lookupClass(false, "jdk.internal.misc.MainMethodFinder"); + Method findMainMethod = ReflectionUtil.lookupMethod(mainMethodFinder, "findMainMethod", Class.class); + javaMainMethod = (Method) findMainMethod.invoke(null, mainClass); + } catch (InvocationTargetException ex) { + assert ex.getTargetException() instanceof NoSuchMethodException; + throw UserError.abort(ex.getCause(), + "Method '%s.%s' is declared as the main entry point but it can not be found. " + + "Make sure that class '%s' is on the classpath and that non-private " + + "method '%s()' or '%s(String[])' exists in that class.", + mainClass.getName(), + mainEntryPointName, + mainClass.getName(), + mainEntryPointName, + mainEntryPointName); + } + } else { + try { + javaMainMethod = ReflectionUtil.lookupMethod(mainClass, mainEntryPointName, String[].class); + final int mainMethodModifiers = javaMainMethod.getModifiers(); + if (!Modifier.isStatic(mainMethodModifiers)) { + throw UserError.abort("Java main method '%s.%s(String[])' is not static.", mainClass.getName(), mainEntryPointName); + } + if (!Modifier.isPublic(mainMethodModifiers)) { + throw UserError.abort("Java main method '%s.%s(String[])' is not public.", mainClass.getName(), mainEntryPointName); + } } catch (ReflectionUtilError ex) { throw UserError.abort(ex.getCause(), "Method '%s.%s' is declared as the main entry point but it can not be found. " + @@ -471,16 +504,11 @@ private int buildImage(ImageClassLoader classLoader) { mainClass.getName(), mainEntryPointName); } + } if (javaMainMethod.getReturnType() != void.class) { - throw UserError.abort("Java main method '%s.%s(String[])' does not have the return type 'void'.", mainClass.getName(), mainEntryPointName); - } - final int mainMethodModifiers = javaMainMethod.getModifiers(); - if (!Modifier.isStatic(mainMethodModifiers)) { - throw UserError.abort("Java main method '%s.%s(String[])' is not static.", mainClass.getName(), mainEntryPointName); - } - if (!Modifier.isPublic(mainMethodModifiers)) { - throw UserError.abort("Java main method '%s.%s(String[])' is not public.", mainClass.getName(), mainEntryPointName); + throw UserError.abort("Java main method '%s.%s(%s)' does not have the return type 'void'.", mainClass.getName(), mainEntryPointName, + javaMainMethod.getParameterCount() == 1 ? "String[]" : ""); } javaMainSupport = createJavaMainSupport(javaMainMethod, classLoader); mainEntryPoint = getMainEntryMethod(classLoader); From 684912abf0e0365a9803a3acc5923a540c3fa46a Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Jun 2023 11:25:20 +0200 Subject: [PATCH 4/7] svm: reformat NativeImageGeneratorRunner --- .../hosted/NativeImageGeneratorRunner.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index b3a5af28b156..b6301a4d6409 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -457,10 +457,10 @@ private int buildImage(ImageClassLoader classLoader) { mainEntryPoint = mainClass.getDeclaredMethod(mainEntryPointName, int.class, CCharPointerPointer.class); } catch (NoSuchMethodException ignored2) { Method javaMainMethod; - /* - * If no C-level main method was found, look for a Java-level main - * method and use our wrapper to invoke it. - */ + /* + * If no C-level main method was found, look for a Java-level main method + * and use our wrapper to invoke it. + */ if ("main".equals(mainEntryPointName) && JavaMainWrapper.instanceMainMethodSupported()) { // Instance main method only supported for "main" method name try { @@ -495,15 +495,15 @@ private int buildImage(ImageClassLoader classLoader) { if (!Modifier.isPublic(mainMethodModifiers)) { throw UserError.abort("Java main method '%s.%s(String[])' is not public.", mainClass.getName(), mainEntryPointName); } - } catch (ReflectionUtilError ex) { - throw UserError.abort(ex.getCause(), - "Method '%s.%s' is declared as the main entry point but it can not be found. " + - "Make sure that class '%s' is on the classpath and that method '%s(String[])' exists in that class.", - mainClass.getName(), - mainEntryPointName, - mainClass.getName(), - mainEntryPointName); - } + } catch (ReflectionUtilError ex) { + throw UserError.abort(ex.getCause(), + "Method '%s.%s' is declared as the main entry point but it can not be found. " + + "Make sure that class '%s' is on the classpath and that method '%s(String[])' exists in that class.", + mainClass.getName(), + mainEntryPointName, + mainClass.getName(), + mainEntryPointName); + } } if (javaMainMethod.getReturnType() != void.class) { From 56b535e0aa38511ddc0a9e8e4d279121502b98ac Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Jun 2023 13:00:33 +0200 Subject: [PATCH 5/7] svm: debuginfo stacktrace changed --- substratevm/mx.substratevm/testhello.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/substratevm/mx.substratevm/testhello.py b/substratevm/mx.substratevm/testhello.py index 2a1268a51e0e..d4bbc2d068d8 100644 --- a/substratevm/mx.substratevm/testhello.py +++ b/substratevm/mx.substratevm/testhello.py @@ -120,11 +120,12 @@ def test(): # expect "#1 0x[0-9a-f]+ in com.oracle.svm.core.code.IsolateEnterStub.JavaMainWrapper_run_.* at [a-z/]+/JavaMainWrapper.java:[0-9]+" exec_string = execute("backtrace") stacktraceRegex = [r"#0%shello\.Hello::main%s %s at hello/Hello\.java:77"%(spaces_pattern, param_types_pattern, arg_values_pattern), - r"#1%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::runCore0%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, no_param_types_pattern, no_arg_values_pattern, package_pattern), - r"#2%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::runCore%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, no_param_types_pattern, no_arg_values_pattern, package_pattern), - r"#3%scom\.oracle\.svm\.core\.JavaMainWrapper::doRun%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, param_types_pattern, arg_values_pattern, package_pattern), - r"#4%s(%s in )?com\.oracle\.svm\.core\.JavaMainWrapper::run%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, param_types_pattern, arg_values_pattern, package_pattern), - r"#5%scom\.oracle\.svm\.core\.code\.IsolateEnterStub::JavaMainWrapper_run_%s%s %s"%(spaces_pattern, hex_digits_pattern, param_types_pattern, arg_values_pattern) + r"#1%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::invokeMain%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, param_types_pattern, arg_values_pattern, package_pattern), + r"#2%s(%s in )?com\.oracle\.svm\.core\.JavaMainWrapper::runCore0%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, no_param_types_pattern, no_arg_values_pattern, package_pattern), + r"#3%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::runCore%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, no_param_types_pattern, no_arg_values_pattern, package_pattern), + r"#4%scom\.oracle\.svm\.core\.JavaMainWrapper::doRun%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, param_types_pattern, arg_values_pattern, package_pattern), + r"#5%s(%s in )?com\.oracle\.svm\.core\.JavaMainWrapper::run%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, param_types_pattern, arg_values_pattern, package_pattern), + r"#6%scom\.oracle\.svm\.core\.code\.IsolateEnterStub::JavaMainWrapper_run_%s%s %s"%(spaces_pattern, hex_digits_pattern, param_types_pattern, arg_values_pattern) ] if musl: # musl has a different entry point - drop the last two frames @@ -364,11 +365,12 @@ def test(): exec_string = execute("backtrace") stacktraceRegex = [r"#0%shello\.Hello\$Greeter::greeter%s %s at hello/Hello\.java:38"%(spaces_pattern, param_types_pattern, arg_values_pattern), r"#1%s%s in hello\.Hello::main%s %s at hello/Hello\.java:77"%(spaces_pattern, address_pattern, param_types_pattern, arg_values_pattern), - r"#2%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::runCore0%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, no_param_types_pattern, no_arg_values_pattern, package_pattern), - r"#3%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::runCore%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, no_param_types_pattern, no_arg_values_pattern, package_pattern), - r"#4%scom\.oracle\.svm\.core\.JavaMainWrapper::doRun%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, param_types_pattern, arg_values_pattern, package_pattern), - r"#5%s(%s in )?com\.oracle\.svm\.core\.JavaMainWrapper::run%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, param_types_pattern, arg_values_pattern, package_pattern), - r"#6%scom\.oracle\.svm\.core\.code\.IsolateEnterStub::JavaMainWrapper_run_%s%s %s"%(spaces_pattern, hex_digits_pattern, param_types_pattern, arg_values_pattern) + r"#2%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::invokeMain%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, param_types_pattern, arg_values_pattern, package_pattern), + r"#3%s(%s in )?com\.oracle\.svm\.core\.JavaMainWrapper::runCore0%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, no_param_types_pattern, no_arg_values_pattern, package_pattern), + r"#4%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::runCore%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, no_param_types_pattern, no_arg_values_pattern, package_pattern), + r"#5%scom\.oracle\.svm\.core\.JavaMainWrapper::doRun%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, param_types_pattern, arg_values_pattern, package_pattern), + r"#6%s(%s in )?com\.oracle\.svm\.core\.JavaMainWrapper::run%s %s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, param_types_pattern, arg_values_pattern, package_pattern), + r"#7%scom\.oracle\.svm\.core\.code\.IsolateEnterStub::JavaMainWrapper_run_%s%s %s"%(spaces_pattern, hex_digits_pattern, param_types_pattern, arg_values_pattern) ] if musl: # musl has a different entry point - drop the last two frames From b1648bdaebcaa788c445841fa8d72f3f166719a6 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Jun 2023 16:08:08 +0200 Subject: [PATCH 6/7] svm: fix Class.getSimpleName() usage --- .../src/com/oracle/svm/core/JavaMainWrapper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java index 2ef312e8ed3d..cb26d9946ffd 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.function.BooleanSupplier; +import com.oracle.svm.util.ClassUtil; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.CurrentIsolate; @@ -121,7 +122,7 @@ public JavaMainSupport(Method javaMainMethod) throws IllegalAccessException { Constructor ctor = ReflectionUtil.lookupConstructor(javaMainMethod.getDeclaringClass()); ctorHandle = MethodHandles.lookup().unreflectConstructor(ctor); } catch (ReflectionUtil.ReflectionUtilError ex) { - throw UserError.abort(ex, "no non-private zero argument constructor found in class %s", javaMainMethod.getDeclaringClass().getSimpleName()); + throw UserError.abort(ex, "No non-private zero argument constructor found in class %s", ClassUtil.getUnqualifiedName(javaMainMethod.getDeclaringClass())); } } this.javaMainHandle = mainHandle; From 1862377c4635a2fd43a1c0905cd117d6de3ff681 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 20 Jun 2023 08:30:31 +0200 Subject: [PATCH 7/7] svm: address review comments --- .../src/com/oracle/svm/core/JavaMainWrapper.java | 1 - .../src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java index cb26d9946ffd..843b3899c377 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java @@ -166,7 +166,6 @@ public List getInputArguments() { } public static void invokeMain(String[] args) throws Throwable { - // This needs to be a local and not a parameter to allow proper constant folding JavaMainSupport javaMainSupport = ImageSingletons.lookup(JavaMainSupport.class); if (javaMainSupport.mainNonstatic) { Object instance = javaMainSupport.javaMainClassCtorHandle.invoke(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index b6301a4d6409..785737b0952f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -478,7 +478,7 @@ private int buildImage(ImageClassLoader classLoader) { throw UserError.abort(ex.getCause(), "Method '%s.%s' is declared as the main entry point but it can not be found. " + "Make sure that class '%s' is on the classpath and that non-private " + - "method '%s()' or '%s(String[])' exists in that class.", + "method '%s()' or '%s(String[])'.", mainClass.getName(), mainEntryPointName, mainClass.getName(),