|
29 | 29 | import static com.oracle.svm.core.option.SubstrateOptionsParser.BooleanOptionFormat.NAME_VALUE;
|
30 | 30 | import static com.oracle.svm.core.option.SubstrateOptionsParser.BooleanOptionFormat.PLUS_MINUS;
|
31 | 31 |
|
| 32 | +import java.lang.invoke.MethodHandle; |
| 33 | +import java.lang.invoke.MethodHandles; |
32 | 34 | //Checkstyle: allow reflection
|
33 | 35 | import java.lang.reflect.Method;
|
34 | 36 | import java.util.ArrayList;
|
@@ -85,21 +87,18 @@ public class JavaMainWrapper {
|
85 | 87 |
|
86 | 88 | public static class JavaMainSupport {
|
87 | 89 |
|
88 |
| - private final Method javaMainMethod; |
| 90 | + final MethodHandle javaMainHandle; |
| 91 | + final String javaMainClassName; |
89 | 92 |
|
90 | 93 | @Platforms(Platform.HOSTED_ONLY.class)
|
91 |
| - public JavaMainSupport(Method javaMainMethod) { |
92 |
| - this.javaMainMethod = javaMainMethod; |
93 |
| - } |
94 |
| - |
95 |
| - private Method getJavaMainMethod() { |
96 |
| - assert javaMainMethod != null; |
97 |
| - return javaMainMethod; |
| 94 | + public JavaMainSupport(Method javaMainMethod) throws IllegalAccessException { |
| 95 | + this.javaMainHandle = MethodHandles.lookup().unreflect(javaMainMethod); |
| 96 | + this.javaMainClassName = javaMainMethod.getDeclaringClass().getName(); |
98 | 97 | }
|
99 | 98 |
|
100 | 99 | public String getJavaCommand() {
|
101 |
| - if (javaMainMethod != null && mainArgs != null) { |
102 |
| - StringBuilder commandLine = new StringBuilder(javaMainMethod.getDeclaringClass().getName()); |
| 100 | + if (mainArgs != null) { |
| 101 | + StringBuilder commandLine = new StringBuilder(javaMainClassName); |
103 | 102 |
|
104 | 103 | for (String arg : mainArgs) {
|
105 | 104 | commandLine.append(' ');
|
@@ -160,28 +159,40 @@ public static int run(int paramArgc, CCharPointerPointer paramArgv) throws Excep
|
160 | 159 | args = RuntimePropertyParser.parse(args);
|
161 | 160 | }
|
162 | 161 | mainArgs = args;
|
163 |
| - final RuntimeSupport rs = RuntimeSupport.getRuntimeSupport(); |
| 162 | + |
164 | 163 | try {
|
165 |
| - try { |
166 |
| - if (AllocationSite.Options.AllocationProfiling.getValue()) { |
167 |
| - Runtime.getRuntime().addShutdownHook(new AllocationSite.AllocationProfilingShutdownHook()); |
168 |
| - } |
169 |
| - if (SubstrateOptions.PrintGCSummary.getValue()) { |
170 |
| - Runtime.getRuntime().addShutdownHook(new PrintGCSummaryShutdownHook()); |
171 |
| - } |
172 |
| - rs.executeStartupHooks(); |
173 |
| - ImageSingletons.lookup(JavaMainSupport.class).getJavaMainMethod().invoke(null, (Object) mainArgs); |
174 |
| - } catch (Throwable ex) { |
175 |
| - JavaThreads.dispatchUncaughtException(Thread.currentThread(), ex); |
| 164 | + if (AllocationSite.Options.AllocationProfiling.getValue()) { |
| 165 | + Runtime.getRuntime().addShutdownHook(new AllocationSite.AllocationProfilingShutdownHook()); |
176 | 166 | }
|
177 |
| - } finally { |
178 |
| - /* Shutdown before joining non-daemon threads. */ |
179 |
| - rs.shutdown(); |
180 |
| - } |
| 167 | + if (SubstrateOptions.PrintGCSummary.getValue()) { |
| 168 | + Runtime.getRuntime().addShutdownHook(new PrintGCSummaryShutdownHook()); |
| 169 | + } |
| 170 | + RuntimeSupport.getRuntimeSupport().executeStartupHooks(); |
| 171 | + |
| 172 | + /* |
| 173 | + * Invoke the application's main method. Invoking the main method via a method handle |
| 174 | + * preserves exceptions, while invoking the main method via reflection would wrap |
| 175 | + * exceptions in a InvocationTargetException. |
| 176 | + */ |
| 177 | + ImageSingletons.lookup(JavaMainSupport.class).javaMainHandle.invokeExact(args); |
181 | 178 |
|
182 |
| - JavaThreads.singleton().joinAllNonDaemons(); |
183 |
| - Counter.logValues(); |
| 179 | + } catch (Throwable ex) { |
| 180 | + JavaThreads.dispatchUncaughtException(Thread.currentThread(), ex); |
184 | 181 |
|
| 182 | + } finally { |
| 183 | + /* |
| 184 | + * Shutdown sequence: First wait for all non-daemon threads to exit. |
| 185 | + */ |
| 186 | + JavaThreads.singleton().joinAllNonDaemons(); |
| 187 | + /* |
| 188 | + * Run shutdown hooks (both our own hooks and application-registered hooks. Note that |
| 189 | + * this can start new non-daemon threads. We are not responsible to wait until they have |
| 190 | + * exited. |
| 191 | + */ |
| 192 | + RuntimeSupport.getRuntimeSupport().shutdown(); |
| 193 | + |
| 194 | + Counter.logValues(); |
| 195 | + } |
185 | 196 | return 0;
|
186 | 197 | }
|
187 | 198 |
|
|
0 commit comments