Java 我能否阻止JLI#U Launch呼叫呼叫方';s";int main(int argc,char*argv[])“;?

Java 我能否阻止JLI#U Launch呼叫呼叫方';s";int main(int argc,char*argv[])“;?,java,macos,launch,Java,Macos,Launch,在调用JLI_Launch之前,我是否可以做一些简单的事情来防止其macOS引导行为(在linux上不会发生)?或者我必须继续阅读更多关于的内容,并使用除JLI_Launch(例如JNI_CreateJavaVM)以外的其他内容吗?如果你想知道为什么这么复杂的启动器,如果我不使用它的架构(不创建子进程),那么将文件放到应用程序的图标上(是否停靠)会打开应用程序,但应用程序没有看到文件放置事件 JLI_Launch的行为就像代码如下所示: static int callCount = 0; int

在调用
JLI_Launch
之前,我是否可以做一些简单的事情来防止其macOS引导行为(在linux上不会发生)?或者我必须继续阅读更多关于的内容,并使用除
JLI_Launch
(例如
JNI_CreateJavaVM
)以外的其他内容吗?如果你想知道为什么这么复杂的启动器,如果我不使用它的架构(不创建子进程),那么将文件放到应用程序的图标上(是否停靠)会打开应用程序,但应用程序没有看到文件放置事件

JLI_Launch
的行为就像代码如下所示:

static int callCount = 0;
int JLI_Launch (/* parameters */) {
     if (callCount == 0) {
        callCount = 1;
        /* figure out what to tell the caller by creating argc,argv */
        main(argc, argv);
     } else {
        callCount = 0;
        // launch the VM
     }
     return 0;
}
在调用
dlopen
dlsym
后调用
JLI\u Launch
。然后,
JLI_Launch
函数调用appbundler的
main
,该函数重复所有操作,使用相同的参数再次调用
JLI_Launch
。第二次调用
JLI_Launch
,虚拟机将运行java代码

除了在准备代码的第二次执行时可能发生的一些奇怪的灾难(例如,选择与第一次执行时选择的版本不同的Java版本),为调用
JLI_Launch
做准备而执行的代码量非常大。为相同的结果执行两次是浪费

这里是MCV的例子。我知道这是C而不是Objective-C,但这部分并不重要。至少它似乎没什么关系,因为它再现了我认为不受欢迎的“BooTrasppy”行为。
#include <stdio.h>
#include <dlfcn.h>
#include "jni.h"

int main ( int argc, char *argv[] ) {
    // The code required to identify jargv is somewhat significant.
    char * jargv[] = { "test.exe", "Test", "Hello, world." };
    int jargc = sizeof(jargv) / sizeof(jargv[0]);
    // The code required to identify lib is significant.
    char * lib = "/Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home/jre/lib/jli/libjli.dylib";
    void * h = dlopen(lib, RTLD_LAZY);
    void (*launcher)() = dlsym(h, "JLI_Launch");
    puts("calling JLI_Launch");
    launcher(jargc, jargv,
             0, NULL, 0, NULL,
             "", "", "java", "java",
             JNI_FALSE, JNI_FALSE, JNI_FALSE,
             (jint) 0);
    return 0;
}
CLG:

下面是使用调试器的更多证据:

$ lldb test.exe
(lldb) target create "test.exe"
Current executable set to '.../test.exe' (x86_64).
(lldb) b main
Breakpoint 1: where = test.exe`main + 40 at test.c:6:12, address = 0x0000000100003da8
(lldb) r
Process 27252 launched: '.../test.exe' (x86_64)
Process 27252 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100003da8 test.exe`main(argc=1, argv=0x00007ffeefbfeb00) at test.c:6:12
   3    #include "jni.h"
   4
   5    int main ( int argc, char *argv[] ) {
-> 6        char * jargv[] = { "test.exe", "Test", "Hello, world." };
                   ^
   7        int jargc = sizeof(jargv) / sizeof(jargv[0]);
   8        char * lib = "/Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home/jre/lib/jli/libjli.dylib";
   9        void * h = dlopen(lib, RTLD_LAZY);
Target 0: (test.exe) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x0000000100003da8 test.exe`main(argc=1, argv=0x00007ffeefbfeb00) at test.c:6:12
    frame #1: 0x00007fff20659621 libdyld.dylib`start + 1
(lldb) c
Process 27252 resuming
22 locations added to breakpoint 1
calling JLI_Launch
Process 27252 stopped
* thread #2, stop reason = breakpoint 1.1
    frame #0: 0x0000000100003da8 test.exe`main(argc=3, argv=0x0000000100307a70) at test.c:6:12
   3    #include "jni.h"
   4
   5    int main ( int argc, char *argv[] ) {
-> 6        char * jargv[] = { "test.exe", "Test", "Hello, world." };
                   ^
   7        int jargc = sizeof(jargv) / sizeof(jargv[0]);
   8        char * lib = "/Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home/jre/lib/jli/libjli.dylib";
   9        void * h = dlopen(lib, RTLD_LAZY);
Target 0: (test.exe) stopped.
(lldb) bt
* thread #2, stop reason = breakpoint 1.1
  * frame #0: 0x0000000100003da8 test.exe`main(argc=3, argv=0x0000000100307a70) at test.c:6:12
    frame #1: 0x000000010015e31f libjli.dylib`apple_main + 84
    frame #2: 0x00007fff2063e950 libsystem_pthread.dylib`_pthread_start + 224
    frame #3: 0x00007fff2063a47b libsystem_pthread.dylib`thread_start + 15
(lldb)
后记 启动程序代码异常的一个线索是,任何地方都没有头文件包含字符串
JLI 
。我只能在
JNI\ucode>函数定义中找到,并且只能在
JNI.h
中找到

“引导”的另一个线索是
JLI\u Launch
调用
main
,调用的
argc
argv
\u start
使用的不同。但我不明白为什么我会在意,因为代码两次都向
JLI_Launch
发送相同的值。如果我认为反馈是必要的,那么我会接受它,但我认为没有

另一个线索是,在linux上,至少在JDK1.8.0_121上,这种行为并不存在。我不得不做一些意想不到的事情来让它工作:

1. call the executable bin/java instead of test.exe
2. soft link the JDK lib folder

显然,在linux上,java调用dlopen根据其对主文件夹的了解来链接其库。

在查看我发布的回溯后,我意识到两件事:

1. I see the name of the calling function, `apple_main`
2. I might be able to find its definition if I download Java SE 16's source code
我在
src/java.base/macosx/native/libjli/java\u md\u macosx.m
中找到了apple\u main的定义:

/*
 * Unwrap the arguments and re-run main()
 */
static void *apple_main (void *arg)
{
    if (main_fptr == NULL) {
#ifdef STATIC_BUILD
        extern int main(int argc, char **argv);
        main_fptr = &main;
#else
        main_fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
#endif
        if (main_fptr == NULL) {
            JLI_ReportErrorMessageSys("error locating main entrypoint\n");
            exit(1);
        }
    }

    struct NSAppArgs *args = (struct NSAppArgs *) arg;
    exit(main_fptr(args->argc, args->argv));
}
pthread\u start
的调用(根据定义)隐藏了一些调用序列(以堆栈形式显示),如下所示:

test.c: main (new main thread)
src/java.base/macosx/native/libjli/java_md_macosx.m: apple_main (new main thread)
src/java.base/macosx/native/libjli/java_md_macosx.m: MacOSXStartup (main thread)
src/java.base/macosx/native/libjli/java_md_macosx.m: CreateExecutionEnvironment (main thread)
src/java.base/share/native/libjli/java.c: JLI_Launch (main thread)
test.c: main (main thread)
我现在可以开始了

/*
 * Unwrap the arguments and re-run main()
 */
static void *apple_main (void *arg)
{
    if (main_fptr == NULL) {
#ifdef STATIC_BUILD
        extern int main(int argc, char **argv);
        main_fptr = &main;
#else
        main_fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
#endif
        if (main_fptr == NULL) {
            JLI_ReportErrorMessageSys("error locating main entrypoint\n");
            exit(1);
        }
    }

    struct NSAppArgs *args = (struct NSAppArgs *) arg;
    exit(main_fptr(args->argc, args->argv));
}
test.c: main (new main thread)
src/java.base/macosx/native/libjli/java_md_macosx.m: apple_main (new main thread)
src/java.base/macosx/native/libjli/java_md_macosx.m: MacOSXStartup (main thread)
src/java.base/macosx/native/libjli/java_md_macosx.m: CreateExecutionEnvironment (main thread)
src/java.base/share/native/libjli/java.c: JLI_Launch (main thread)
test.c: main (main thread)