Skip to content

Commit bb82bc3

Browse files
committed
[GR-65777] Adopt "JDK-8344706: Implement JEP 512: Compact Source Files and Instance Main Methods"
PullRequest: graal/21076
2 parents d066dd4 + 4a7cd35 commit bb82bc3

File tree

3 files changed

+39
-53
lines changed

3 files changed

+39
-53
lines changed

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -881,33 +881,29 @@ def _cinterfacetutorial(native_image, args=None):
881881
}
882882
''',
883883
'noArgs': '''
884-
// requires JDK 21 and --enable-preview
885884
public class HelloWorld {
886885
static void main() {
887886
System.out.println(System.getenv("%s"));
888887
}
889888
}
890889
''',
891890
'instance': '''
892-
// requires JDK 21 and --enable-preview
893891
class HelloWorld {
894892
void main(String[] args) {
895893
System.out.println(System.getenv("%s"));
896894
}
897895
}
898896
''',
899897
'instanceNoArgs': '''
900-
// requires JDK 21 and --enable-preview
901898
class HelloWorld {
902899
void main() {
903900
System.out.println(System.getenv("%s"));
904901
}
905902
}
906903
''',
907904
'unnamedClass': '''
908-
// requires JDK 21 and javac --enable-preview --source 21 and native-image --enable-preview
909905
void main() {
910-
System.out.println(System.getenv("%s"));
906+
IO.println(System.getenv("%s"));
911907
}
912908
''',
913909
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -113,30 +113,22 @@ public static class JavaMainSupport implements ApplicationLayerOnlyImageSingleto
113113

114114
@Platforms(Platform.HOSTED_ONLY.class)
115115
public JavaMainSupport(Method javaMainMethod) throws IllegalAccessException {
116-
if (instanceMainMethodSupported()) {
117-
javaMainMethod.setAccessible(true);
118-
int mods = javaMainMethod.getModifiers();
119-
this.mainNonstatic = !Modifier.isStatic(mods);
120-
this.mainWithoutArgs = javaMainMethod.getParameterCount() == 0;
121-
MethodHandle mainHandle = MethodHandles.lookup().unreflect(javaMainMethod);
122-
MethodHandle ctorHandle = null;
123-
if (mainNonstatic) {
124-
// Instance main
125-
try {
126-
Constructor<?> ctor = ReflectionUtil.lookupConstructor(javaMainMethod.getDeclaringClass());
127-
ctorHandle = MethodHandles.lookup().unreflectConstructor(ctor);
128-
} catch (ReflectionUtil.ReflectionUtilError ex) {
129-
throw UserError.abort(ex, "No non-private zero argument constructor found in class %s", ClassUtil.getUnqualifiedName(javaMainMethod.getDeclaringClass()));
130-
}
116+
int mods = javaMainMethod.getModifiers();
117+
this.mainNonstatic = !Modifier.isStatic(mods);
118+
this.mainWithoutArgs = javaMainMethod.getParameterCount() == 0;
119+
MethodHandle mainHandle = MethodHandles.lookup().unreflect(javaMainMethod);
120+
MethodHandle ctorHandle = null;
121+
if (mainNonstatic) {
122+
// Instance main
123+
try {
124+
Constructor<?> ctor = ReflectionUtil.lookupConstructor(javaMainMethod.getDeclaringClass());
125+
ctorHandle = MethodHandles.lookup().unreflectConstructor(ctor);
126+
} catch (ReflectionUtil.ReflectionUtilError ex) {
127+
throw UserError.abort(ex, "No non-private zero argument constructor found in class %s", ClassUtil.getUnqualifiedName(javaMainMethod.getDeclaringClass()));
131128
}
132-
this.javaMainHandle = mainHandle;
133-
this.javaMainClassCtorHandle = ctorHandle;
134-
} else {
135-
this.mainNonstatic = false;
136-
this.mainWithoutArgs = false;
137-
this.javaMainHandle = MethodHandles.lookup().unreflect(javaMainMethod);
138-
this.javaMainClassCtorHandle = null;
139129
}
130+
this.javaMainHandle = mainHandle;
131+
this.javaMainClassCtorHandle = ctorHandle;
140132
this.javaMainClassName = javaMainMethod.getDeclaringClass().getName();
141133
}
142134

@@ -199,20 +191,6 @@ public static void invokeMain(String[] args) throws Throwable {
199191
}
200192
}
201193

202-
/**
203-
* Determines whether instance main methodes are enabled. See JDK-8306112: Implementation of JEP
204-
* 445: Unnamed Classes and Instance Main Methods (Preview).
205-
*/
206-
@Platforms(Platform.HOSTED_ONLY.class)
207-
public static boolean instanceMainMethodSupported() {
208-
var previewFeature = ReflectionUtil.lookupClass(true, "jdk.internal.misc.PreviewFeatures");
209-
try {
210-
return previewFeature != null && (Boolean) previewFeature.getDeclaredMethod("isEnabled").invoke(null);
211-
} catch (ReflectiveOperationException e) {
212-
throw VMError.shouldNotReachHere(e);
213-
}
214-
}
215-
216194
@Uninterruptible(reason = "The caller initialized the thread state, so the callees do not need to be uninterruptible.", calleeMustBe = false)
217195
private static int runCore() {
218196
return runCore0();

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import com.oracle.svm.core.SubstrateOptions;
6565
import com.oracle.svm.core.option.HostedOptionKey;
6666
import com.oracle.svm.core.option.SubstrateOptionsParser;
67+
import com.oracle.svm.core.util.BasedOnJDKFile;
6768
import com.oracle.svm.core.util.ExitStatus;
6869
import com.oracle.svm.core.util.InterruptImageBuilding;
6970
import com.oracle.svm.core.util.UserError;
@@ -495,19 +496,9 @@ private int buildImage(ImageClassLoader classLoader) {
495496
* If no C-level main method was found, look for a Java-level main method
496497
* and use our wrapper to invoke it.
497498
*/
498-
if ("main".equals(mainEntryPointName) && JavaMainWrapper.instanceMainMethodSupported()) {
499-
// Instance main method only supported for "main" method name
499+
if ("main".equals(mainEntryPointName)) {
500500
try {
501-
/*
502-
* JDK-8306112: Implementation of JEP 445: Unnamed Classes and
503-
* Instance Main Methods (Preview)
504-
*
505-
* MainMethodFinder will perform all the necessary checks
506-
*/
507-
String mainMethodFinderClassName = "jdk.internal.misc.MethodFinder";
508-
Class<?> mainMethodFinder = ReflectionUtil.lookupClass(false, mainMethodFinderClassName);
509-
Method findMainMethod = ReflectionUtil.lookupMethod(mainMethodFinder, "findMainMethod", Class.class);
510-
javaMainMethod = (Method) findMainMethod.invoke(null, mainClass);
501+
javaMainMethod = findDefaultJavaMainMethod(mainClass);
511502
} catch (InvocationTargetException ex) {
512503
assert ex.getTargetException() instanceof NoSuchMethodException;
513504
throw UserError.abort(ex.getCause(),
@@ -618,6 +609,27 @@ private int buildImage(ImageClassLoader classLoader) {
618609
return ExitStatus.OK.getValue();
619610
}
620611

612+
/*
613+
* Finds the main method using the {@code jdk.internal.misc.MethodFinder}.
614+
*
615+
* The {@code MethodFinder} was introduced by JDK-8344706 (Implement JEP 512: Compact Source
616+
* Files and Instance Main Methods) and will perform all the necessary checks.
617+
*/
618+
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+24/src/java.base/share/classes/jdk/internal/misc/MethodFinder.java#L45-L106")
619+
private static Method findDefaultJavaMainMethod(Class<?> mainClass) throws IllegalAccessException, InvocationTargetException {
620+
Class<?> mainMethodFinder = ReflectionUtil.lookupClass(false, "jdk.internal.misc.MethodFinder");
621+
Method findMainMethod = ReflectionUtil.lookupMethod(mainMethodFinder, "findMainMethod", Class.class);
622+
/*
623+
* We are using Method.invoke and throwing checked exceptions on purpose instead of
624+
* ReflectionUtil to issue a proper error message.
625+
*/
626+
Method invoke = (Method) findMainMethod.invoke(null, mainClass);
627+
/*
628+
* Use ReflectionUtil get a Method object with the right accessibility.
629+
*/
630+
return ReflectionUtil.lookupMethod(invoke.getDeclaringClass(), invoke.getName(), invoke.getParameterTypes());
631+
}
632+
621633
private static void reportConflictingOptions(HostedOptionKey<Boolean> o1, HostedOptionKey<?> o2) {
622634
throw UserError.abort("Cannot pass both options: %s and %s", SubstrateOptionsParser.commandArgument(o1, "+"), SubstrateOptionsParser.commandArgument(o2, "+"));
623635
}

0 commit comments

Comments
 (0)