8315458: Implement JEP 463: Implicitly Declared Classes and Instance Main Method (Second Preview)

Reviewed-by: jlahoda, mcimadamore, vromero, rriggs, alanb, mchung
This commit is contained in:
Jim Laskey 2023-11-30 12:49:49 +00:00
parent 03759e892d
commit 04ad98ed32
48 changed files with 612 additions and 664 deletions

View file

@ -387,6 +387,84 @@ JLI_Launch(int argc, char ** argv, /* main argc, argv */
} \
} while (JNI_FALSE)
#define CHECK_EXCEPTION_FAIL() \
do { \
if ((*env)->ExceptionOccurred(env)) { \
(*env)->ExceptionClear(env); \
return 0; \
} \
} while (JNI_FALSE)
#define CHECK_EXCEPTION_NULL_FAIL(mainObject) \
do { \
if ((*env)->ExceptionOccurred(env)) { \
(*env)->ExceptionClear(env); \
return 0; \
} else if (mainObject == NULL) { \
return 0; \
} \
} while (JNI_FALSE)
/*
* Invoke a static main with arguments. Returns 1 (true) if successful otherwise
* processes the pending exception from GetStaticMethodID and returns 0 (false).
*/
int
invokeStaticMainWithArgs(JNIEnv *env, jclass mainClass, jobjectArray mainArgs) {
jmethodID mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
CHECK_EXCEPTION_FAIL();
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
return 1;
}
/*
* Invoke an instance main with arguments. Returns 1 (true) if successful otherwise
* processes the pending exception from GetMethodID and returns 0 (false).
*/
int
invokeInstanceMainWithArgs(JNIEnv *env, jclass mainClass, jobjectArray mainArgs) {
jmethodID constructor = (*env)->GetMethodID(env, mainClass, "<init>", "()V");
CHECK_EXCEPTION_FAIL();
jobject mainObject = (*env)->NewObject(env, mainClass, constructor);
CHECK_EXCEPTION_NULL_FAIL(mainObject);
jmethodID mainID = (*env)->GetMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
CHECK_EXCEPTION_FAIL();
(*env)->CallVoidMethod(env, mainObject, mainID, mainArgs);
return 1;
}
/*
* Invoke a static main without arguments. Returns 1 (true) if successful otherwise
* processes the pending exception from GetStaticMethodID and returns 0 (false).
*/
int
invokeStaticMainWithoutArgs(JNIEnv *env, jclass mainClass) {
jmethodID mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"()V");
CHECK_EXCEPTION_FAIL();
(*env)->CallStaticVoidMethod(env, mainClass, mainID);
return 1;
}
/*
* Invoke an instance main without arguments. Returns 1 (true) if successful otherwise
* processes the pending exception from GetMethodID and returns 0 (false).
*/
int
invokeInstanceMainWithoutArgs(JNIEnv *env, jclass mainClass) {
jmethodID constructor = (*env)->GetMethodID(env, mainClass, "<init>", "()V");
CHECK_EXCEPTION_FAIL();
jobject mainObject = (*env)->NewObject(env, mainClass, constructor);
CHECK_EXCEPTION_NULL_FAIL(mainObject);
jmethodID mainID = (*env)->GetMethodID(env, mainClass, "main",
"()V");
CHECK_EXCEPTION_FAIL();
(*env)->CallVoidMethod(env, mainObject, mainID);
return 1;
}
int
JavaMain(void* _args)
@ -403,9 +481,6 @@ JavaMain(void* _args)
jclass mainClass = NULL;
jclass appClass = NULL; // actual application class being launched
jobjectArray mainArgs;
jmethodID mainID;
jmethodID constructor;
jobject mainObject;
int ret = 0;
jlong start = 0, end = 0;
@ -491,9 +566,6 @@ JavaMain(void* _args)
ret = 1;
/*
* Get the application's main class. It also checks if the main
* method exists.
*
* See bugid 5030265. The Main-Class name has already been parsed
* from the manifest, but not parsed properly for UTF-8 support.
* Hence the code here ignores the value previously extracted and
@ -523,7 +595,7 @@ JavaMain(void* _args)
* consistent in the UI we need to track and report the application main class.
*/
appClass = GetApplicationClass(env);
NULL_CHECK_RETURN_VALUE(appClass, -1);
CHECK_EXCEPTION_NULL_LEAVE(appClass);
/* Build platform specific argument array */
mainArgs = CreateApplicationArgs(env, argv, argc);
@ -545,59 +617,15 @@ JavaMain(void* _args)
CHECK_EXCEPTION_LEAVE(1);
/*
* The LoadMainClass not only loads the main class, it will also ensure
* that the main method's signature is correct, therefore further checking
* is not required. The main method is invoked here so that extraneous java
* stacks are not in the application stack trace.
* The main method is invoked here so that extraneous java stacks are not in
* the application stack trace.
*/
#define MAIN_WITHOUT_ARGS 1
#define MAIN_NONSTATIC 2
jclass helperClass = GetLauncherHelperClass(env);
jmethodID getMainType = (*env)->GetStaticMethodID(env, helperClass,
"getMainType",
"()I");
CHECK_EXCEPTION_NULL_LEAVE(getMainType);
int mainType = (*env)->CallStaticIntMethod(env, helperClass, getMainType);
CHECK_EXCEPTION_LEAVE(mainType);
switch (mainType) {
case 0: {
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
CHECK_EXCEPTION_NULL_LEAVE(mainID);
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
break;
}
case MAIN_WITHOUT_ARGS: {
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"()V");
CHECK_EXCEPTION_NULL_LEAVE(mainID);
(*env)->CallStaticVoidMethod(env, mainClass, mainID);
break;
}
case MAIN_NONSTATIC: {
constructor = (*env)->GetMethodID(env, mainClass, "<init>", "()V");
CHECK_EXCEPTION_NULL_LEAVE(constructor);
mainObject = (*env)->NewObject(env, mainClass, constructor);
CHECK_EXCEPTION_NULL_LEAVE(mainObject);
mainID = (*env)->GetMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
CHECK_EXCEPTION_NULL_LEAVE(mainID);
(*env)->CallVoidMethod(env, mainObject, mainID, mainArgs);
break;
}
case MAIN_NONSTATIC | MAIN_WITHOUT_ARGS: {
constructor = (*env)->GetMethodID(env, mainClass, "<init>", "()V");
CHECK_EXCEPTION_NULL_LEAVE(constructor);
mainObject = (*env)->NewObject(env, mainClass, constructor);
CHECK_EXCEPTION_NULL_LEAVE(mainObject);
mainID = (*env)->GetMethodID(env, mainClass, "main",
"()V");
CHECK_EXCEPTION_NULL_LEAVE(mainID);
(*env)->CallVoidMethod(env, mainObject, mainID);
break;
}
if (!invokeStaticMainWithArgs(env, mainClass, mainArgs) &&
!invokeInstanceMainWithArgs(env, mainClass, mainArgs) &&
!invokeStaticMainWithoutArgs(env, mainClass) &&
!invokeInstanceMainWithoutArgs(env, mainClass)) {
ret = 1;
LEAVE();
}
/*
@ -1593,8 +1621,9 @@ NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
}
/*
* Loads a class and verifies that the main class is present and it is ok to
* call it for more details refer to the java implementation.
* Calls LauncherHelper::checkAndLoadMain to verify that the main class
* is present, it is ok to load the main class and then load the main class.
* For more details refer to the java implementation.
*/
static jclass
LoadMainClass(JNIEnv *env, int mode, char *name)