diff --git a/src/main/java/com/oracle/dalvik/VMLauncher.java b/src/main/java/com/oracle/dalvik/VMLauncher.java index 9586e15f..c59f0517 100644 --- a/src/main/java/com/oracle/dalvik/VMLauncher.java +++ b/src/main/java/com/oracle/dalvik/VMLauncher.java @@ -1,7 +1,54 @@ package com.oracle.dalvik; +import android.util.*; + +import java.util.*; + public final class VMLauncher { private VMLauncher() { } - public static native int launchJVM(String[] args); + public static int launchJVM(boolean useJli, List args) { + System.out.print("Launch method: "); + if (useJli) { + System.out.println("JLI_Launch"); + return launchJVM(args.toArray(new String[0])); + } else { + System.out.println("JNI_JavaVM"); + args.remove(0); + int cpPath = args.indexOf("-cp"); + // int jarPath = Arrays.asList(args).indexOf("-jar"); + if (cpPath != -1) { + String classpath = args.remove(cpPath + 1); + args.set(cpPath, "-Djava.class.path=" + classpath); + + String mainClass = ""; + int mainClassIndex; + for (mainClassIndex = -1; mainClassIndex < args.size(); mainClassIndex++) { + if (!args.get(mainClassIndex).startsWith("-")) { + mainClass = args.get(mainClassIndex); + break; + } + } + + mainClassIndex++; + String[] mainArgs = new String[args.size() - mainClassIndex]; + System.arraycopy( + args.toArray(new String[0]), mainClassIndex, + mainArgs, 0, mainArgs.length + ); + + String[] vmArgs = new String[args.size() - mainArgs.length - 2]; + System.arraycopy( + args.toArray(new String[0]), 0, + vmArgs, 0, vmArgs.length + ); + + return createLaunchMainJVM(vmArgs, mainClass, mainArgs); + } else { + throw new RuntimeException("Invalid or unsupported classpath type"); + } + } + } + private static native int launchJVM(String[] args); + private static native int createLaunchMainJVM(String[] vmArgs, String mainClass, String[] mainArgs); } diff --git a/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java b/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java index 40ae24cb..0fe94bba 100644 --- a/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java +++ b/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java @@ -205,7 +205,7 @@ public class JREUtils initJavaRuntime(); chdir(Tools.DIR_GAME_NEW); - final int exitCode = VMLauncher.launchJVM(javaArgList.toArray(new String[0])); + final int exitCode = VMLauncher.launchJVM(false, javaArgList); System.out.println("Java Exit code: " + exitCode); if (exitCode != 0) { Tools.showError(new Exception("Java exited with code " + exitCode)); diff --git a/src/main/jni/jre_launcher.c b/src/main/jni/jre_launcher.c index 5dce51d7..273c18b5 100644 --- a/src/main/jni/jre_launcher.c +++ b/src/main/jni/jre_launcher.c @@ -35,6 +35,54 @@ #include "utils.h" +JNIEXPORT jint JNICALL Java_com_oracle_dalvik_VMLauncher_createLaunchMainJVM(JNIEnv *env, jclass clazz, jobjectArray vmArgArr, jstring mainClassStr, jobjectArray mainArgArr) { + void *libjvm = dlopen("/usr/lib/jvm/java-16-openjdk/lib/server/libjvm.dylib", RTLD_NOW + RTLD_GLOBAL); + if (libjvm == NULL) { + printf("dlopen failed to open libjvm.dylib (dlerror %s).", dlerror()); + return -1; + } + + JNI_CreateJavaVM_func *jl_JNI_CreateJavaVM = (JNI_CreateJavaVM_func *) dlsym(libjvm, "JNI_CreateJavaVM"); + if (jl_JNI_CreateJavaVM == NULL) { + printf("dlsym failed to get JNI_CreateJavaVM (dlerror %s).\n", dlerror()); + return -2; + } + + int vm_argc = (*env)->GetArrayLength(env, vmArgArr); + char **vm_argv = convert_to_char_array(env, vmArgArr); + + int main_argc = (*env)->GetArrayLength(env, mainArgArr); + char **main_argv = convert_to_char_array(env, mainArgArr); + + JavaVMInitArgs vm_args; + JavaVMOption options[vm_argc]; + for (int i = 0; i < vm_argc; i++) { + options[i].optionString = vm_argv[i]; + } + vm_args.version = JNI_VERSION_1_8; + vm_args.options = options; + vm_args.nOptions = vm_argc; + vm_args.ignoreUnrecognized = JNI_FALSE; + + jint res = (jint) jl_JNI_CreateJavaVM(&runtimeJavaVMPtr, (void**)&runtimeJNIEnvPtr_JRE, &vm_args); + // delete options; + + char *main_class_c = (*env)->GetStringUTFChars(env, mainClassStr, 0); + + jclass mainClass = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, main_class_c); + jmethodID mainMethod = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, mainClass, "main", "([Ljava/lang/String;)V"); + + // Need recreate jobjectArray to make JNIEnv is 'runtimeJNIEnvPtr_JRE'. + jobjectArray runtime_main_argv = convert_from_char_array(runtimeJNIEnvPtr_JRE, main_argv, main_argc); + (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(runtimeJNIEnvPtr_JRE, mainClass, mainMethod, runtime_main_argv); + + (*env)->ReleaseStringUTFChars(env, mainClassStr, main_class_c); + free_char_array(env, mainArgArr, main_argv); + free_char_array(env, vmArgArr, vm_argv); + + return res; +} + // PojavLancher: fixme: are these wrong? #define FULL_VERSION "1.16.0-internal" #define DOT_VERSION "1.16"