无话不谈|离 Linux 内核有多远?,Java( 二 )
CallJavaMainInNewThread的主要逻辑如下:
intCallJavaMainInNewThread(jlongstack_size,void*args){intrslt;pthread_ttid;pthread_attr_tattr;pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);if(stack_size>0){pthread_attr_setstacksize(&attr,stack_size);}pthread_attr_setguardsize(&attr,0);//nopthreadguardpageonjavathreadsif(pthread_create(&tid,&attr,ThreadJavaMain,args)==0){void*tmp;pthread_join(tid,&tmp);rslt=(int)(intptr_t)tmp;}else{rslt=JavaMain(args);}pthread_attr_destroy(&attr);returnrslt;}看到pthread_create了吧 , 破案了 , Java的线程就是通过pthread实现的 。 此处就可以进入内核了 , 但是我们还是先继续看看JVM 。 ThreadJavaMain直接调用了JavaMain , 所以这里的逻辑就是 , 如果创建线程成功 , 就由新线程执行JavaMain , 否则就知道在当前进程执行JavaMain 。
JavaMain是我们关注的重点 , 核心逻辑如下:
intJavaMain(void*_args){JavaMainArgs*args=(JavaMainArgs*)_args;intargc=args->argc;char**argv=args->argv;intmode=args->mode;char*what=args->what;InvocationFunctionsifn=args->ifn;JavaVM*vm=0;JNIEnv*env=0;jclassmainClass=NULL;jclassappClass=NULL;//actualapplicationclassbeinglaunchedjmethodIDmainID;jobjectArraymainArgs;intret=0;jlongstart,end;/*Initializethevirtualmachine*/if(!InitializeJVM(&vm,&env,&ifn)){//1JLI_ReportErrorMessage(JVM_ERROR1);exit(1);}mainClass=LoadMainClass(env,mode,what);//2CHECK_EXCEPTION_NULL_LEAVE(mainClass);mainArgs=CreateApplicationArgs(env,argv,argc);CHECK_EXCEPTION_NULL_LEAVE(mainArgs);mainID=(*env)->GetStaticMethodID(env,mainClass,"main","([Ljava/lang/String;)V");//3CHECK_EXCEPTION_NULL_LEAVE(mainID);/*Invokemainmethod.*/(*env)->CallStaticVoidMethod(env,mainClass,mainID,mainArgs);//4ret=(*env)->ExceptionOccurred(env)==NULL?0:1;LEAVE();}第1步 , 调用InitializeJVM初始化JVM 。 InitializeJVM会调用ifn->CreateJavaVM , 也就是libjvm.so中的JNI_CreateJavaVM 。
第2步 , LoadMainClass , 最终调用的是JVM_FindClassFromBootLoader , 也是通过动态链接找到函数(定义在hotspot/share/prims/下) , 然后调用它 。
【无话不谈|离 Linux 内核有多远?,Java】第3和第4步 , Java的同学应该知道 , 这就是调用main函数 。
有点跑题了……我们继续以pthread_create为例看看内核吧 。
其实 , pthread_create离内核还有一小段距离 , 就是glibc(nptl/pthread_create.c) 。 创建线程最终是通过clone系统调用实现的 , 我们不关心glibc的细节(否则又跑偏了) , 就看看它跟直接clone的不同 。
以下关于线程的讨论从书里摘抄过来 。
constintclone_flags=(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SYSVSEM|CLONE_SIGHAND|CLONE_THREAD|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID|0);__clone(&start_thread,stackaddr,clone_flags,pd,&pd->tid,tp,&pd->tid);各个标志的说明如下表(这句话不是摘抄的 。。。 ) 。
推荐阅读
- 无话不谈|全球5G基站建设数量大曝光!中国建成50万个:那欧美国家呢?
- 无话不谈|心动不如行动,赶紧保存,分享一些好看到极致的全面屏手机壁纸
- 无话不谈|已经没有国家能够扼杀中国高端科技,中国芯片崛起已成既定事实
- 通天战队|没有之一,Linux:NVIDIA是我们接触过的最糟糕的公司
- 载风月|关闭终端,程序后台运行,我有5种方法你呢?,Linux运维之
- 小米科技|Linux系统下Java通过shell脚本监控重启服务
- 少年帮|Linux 版已上架统信 UOS 商店,迅雷下载
- 无话不谈|五千电池+128GB,低至1399元,三款超长续航5G手机
- 莫小帅|kernel同步机制(上篇),Linux
- Linux|Linux迎来29周年,我们一起看下Linux一路过来的发展(第一部)