Java--深入JDK和hotspot底层源码剖析Thread的run()、start()方法执行过程_jdk的源码hotspot跟jdk是分开的

    System.out.println(Thread.currentThread().getName());
}

public static void main(String[] args) throws InterruptedException {
    Thread thread1 = new Thread() {
        @Override
        public void run() {
            System.out.println("执行print()方法的线程是:" + Thread.currentThread().getName());
            print();
        }
    };
    System.out.println("一、调用run()方法的线程是:" + Thread.currentThread().getName());
    thread1.run();

    Thread.sleep(1000);

    System.out.println("二、调用start()方法的线程是:" + Thread.currentThread().getName());
    thread1.start();
}

}


**测试结果:**



一、调用run()方法的线程是:main
执行print()方法的线程是:main
print…
main
二、调用start()方法的线程是:main
执行print()方法的线程是:Thread-0
print…
Thread-0


**简单总结:**


* **run()方法调用和执行重写的代码块都是由main主线程来完成的;**
* **start()方法调用是有main()主线程来调用,但是重写的代码块是由`非main`主线程来执行的。**


## 二、源码分析


### 2.1 run()方法


**通过线程调用run()方法,这个其实很简单,比如前面测试代码执行run方法:**



thread1.run();


**Ctrl + 鼠标左键,进入到`java.lang.Thread`的`run()`方法的源码:**



@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

**再Ctrl + Alt + 鼠标左键,定位前面测试类MyThread中重写的run()方法**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c6b4df887dfa4499b1a389f17af44b25.png)  
 **可以发现,直接就调用到重写的run()方法了,并且,你可以重复调用多次,而且每一次都是由main主线程调用run()方法,然后非main主线程,执行run()方法代码块**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c652e22e698c496ba2557de7a59ed1cc.png)  
 **虽然run()方法也可以直接执行到重写的代码块,不过实际当中,按规范来说,不会直接调用run()执行,而是通过start()方法来开启线程,start()方法底层会判断线程的状态,开启线程,最终调用run()方法并结束线程状态,往后了解。**


### 2.2 start()方法


**Oracle JDK源码`stat()`方法:**



public class Thread implements Runnable {

private ThreadGroup group;
private volatile int threadStatus = 0;

public synchronized void start() {
//如果线程状态不是0-新建,则抛异常
if (threadStatus != 0)
throw new IllegalThreadStateException();

    //将当前线程添加到线程组
    group.add(this);
	
	//线程是否开启,默认false-未开启
    boolean started = false;
    try {
        //调用native本地方法(最终调用run()方法的核心入口)
        start0();
        //执行完start0,说明线程已正常启动
        started = true;
    } finally {
        try {
            if (!started) {
                //线程启动失败,则从线程组中将该线程删除
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
            ...
        }
    }
}

**难点和重点是调用的`start0()`方法,这是一个native(本地方法/底层方法),源码:**



//native本地方法,底层开启异步线程,由JVM创建并启动线程,并最终调用run()方法
private native void start0();


**由于Oracle JDK对于native本地方法的源码隐藏了具体实现,可以去Open JDK官方或Github下载源码**


**以下载open jdk8最新的源码版本jdk8u60为例,需要下载`jdk`和`hotspot`两种源码来研究**


* **下载`jdk8u60`源码**  
 <http://hg.openjdk.java.net/jdk8u/jdk8u60/jdk/file/935758609767>  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/1ced0e4f100f4d2786c217e9563e3955.png)
* **下载jdk8u60的`hotspot`源码**  
 <http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd>  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/4193a7e6ba734d1bb45866c866a7dbd5.png)  
 **最后发现Open JDK官网下载实在是太慢了,而且还需要分别下载jdk8u60和jdk8u60\_hotspot的源码**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2613a5d4186141afa7769a74cab6973e.png)




---


**不过现在OpenJDK的源码已经放到GitHub,可以直接去GitHub下载,而且jdk源码和hotspot源码直接放一起了,省事,这里以下载`jdk8-b60`示例,下载地址:**


<https://github.com/openjdk/jdk/releases/tag/jdk8-b60>


**下载完解压,主要关注jdk和hotspot这两个源码目录:**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/72484ca9f7ca414885ef690111dc537c.png)  
 **使用相关工具,比如`Scource Insight`查看底层方法`native stat0`具体源码实现**  
 [(教程)安装Scource Insight]( )  
 [(教程)使用Scource Insight打开OpenJDK源码]( )  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f80461597fef4dcb811e0a736dc1b689.png)


**接下来通过Scource Insight查看底层方法start0是如何一步步,最终由主线程调用Thread#run()方法的源码分析过程**


**首先查看**  
 **源码文件:\jdk-jdk8-b60\jdk\src\share\native\java\lang\ `Thread.c`**  
 **关键源码:`JVM_StartThread`**



static JNINativeMethod methods[] = {
{“start0”, “()V”, (void *)&JVM_StartThread},//JVM开启线程的主入口
{“stop0”, “(” OBJ “)V”, (void *)&JVM_StopThread},
{“isAlive”, “()Z”, (void *)&JVM_IsThreadAlive},
{“suspend0”, “()V”, (void *)&JVM_SuspendThread},
{“resume0”, “()V”, (void *)&JVM_ResumeThread},
{“setPriority0”, “(I)V”, (void *)&JVM_SetThreadPriority},
{“yield”, “()V”, (void *)&JVM_Yield},
{“sleep”, “(J)V”, (void *)&JVM_Sleep},
{“currentThread”, “()” THD, (void *)&JVM_CurrentThread},
{“countStackFrames”, “()I”, (void *)&JVM_CountStackFrames},
{“interrupt0”, “()V”, (void *)&JVM_Interrupt},
{“isInterrupted”, “(Z)Z”, (void *)&JVM_IsInterrupted},
{“holdsLock”, “(” OBJ “)Z”, (void *)&JVM_HoldsLock},
{“getThreads”, “()[” THD, (void *)&JVM_GetAllThreads},
{“dumpThreads”, “([” THD “)[[” STE, (void *)&JVM_DumpThreads},
{“setNativeName”, “(” STR “)V”, (void *)&JVM_SetNativeThreadName},
};


**源码文件:\jdk-jdk8-b60\hotspot\src\share\vm\prims\ `jvm.cpp`  
 关键源码:`new JavaThread`**



JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
JVMWrapper(“JVM_StartThread”);
JavaThread *native_thread = NULL;
bool throw_illegal_thread_state = false;

{
MutexLocker mu(Threads_lock);

if (java_lang_Thread::thread(JNIHandles::resolve\_non\_null(jthread)) != NULL) {
  throw_illegal_thread_state = true;
} else {

  jlong size =
         java_lang_Thread::stackSize(JNIHandles::resolve\_non\_null(jthread));
  size\_t sz = size > 0 ? (size\_t) size : 0;
  native_thread = new JavaThread(&thread_entry, sz);

  if (native_thread->osthread() != NULL) {
    native_thread->prepare(jthread);
  }
}

}

if (throw_illegal_thread_state) {
THROW(vmSymbols::java_lang_IllegalThreadStateException());
}

assert(native_thread != NULL, “Starting null thread?”);

if (native_thread->osthread() == NULL) {
delete native_thread;
if (JvmtiExport::should_post_resource_exhausted()) {
JvmtiExport::post_resource_exhausted(
JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,
“unable to create new native thread”);
}
THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
“unable to create new native thread”);
}

Thread::start(native_thread);

JVM_END


**源码文件:\jdk-jdk8-b60\hotspot\src\share\vm\prims\ `jvm.cpp`**  
 **关键源码:set\_thread\_status**\*`RUNNABLE`\*\*



void Thread::start(Thread* thread) {
trace(“start”, thread);
if (!DisableStartThread) {
if (thread->is_Java_thread()) {
java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),
java_lang_Thread::RUNNABLE);//设置线程状态为RUNNABLE-运行状态
}
os::start_thread(thread);
}
}


**源码文件:\jdk-jdk8-b60\hotspot\src\share\vm\runtime\ `os.cpp`  
 关键源码:osthread->set\_state(`RUNNABLE`)**



本人从事网路安全工作12年,曾在2个大厂工作过,安全服务、售后服务、售前、攻防比赛、安全讲师、销售经理等职位都做过,对这个行业了解比较全面。


最近遍览了各种网络安全类的文章,内容参差不齐,其中不伐有大佬倾力教学,也有各种不良机构浑水摸鱼,在收到几条私信,发现大家对一套完整的系统的网络安全从学习路线到学习资料,甚至是工具有着不小的需求。


最后,我将这部分内容融会贯通成了一套282G的网络安全资料包,所有类目条理清晰,知识点层层递进,需要的小伙伴可以点击下方小卡片领取哦!下面就开始进入正题,如何从一个萌新一步一步进入网络安全行业。


![](https://img-blog.csdnimg.cn/img_convert/311903982dea1d8a5d2c98fc271b5b41.jpeg)



### 学习路线图


 其中最为瞩目也是最为基础的就是网络安全学习路线图,这里我给大家分享一份打磨了3个月,已经更新到4.0版本的网络安全学习路线图。


相比起繁琐的文字,还是生动的视频教程更加适合零基础的同学们学习,这里也是整理了一份与上述学习路线一一对应的网络安全视频教程。


![](https://img-blog.csdnimg.cn/img_convert/1ddfaf7dc5879b1120e31fafa1ad4dc7.jpeg)


#### 网络安全工具箱


当然,当你入门之后,仅仅是视频教程已经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份**我自己整理的网络安全入门工具以及使用教程和实战。**


![](https://img-blog.csdnimg.cn/img_convert/bcd1787ce996787388468bb227d8f959.jpeg)


#### 项目实战


最后就是项目实战,这里带来的是**SRC资料&HW资料**,毕竟实战是检验真理的唯一标准嘛~


![](https://img-blog.csdnimg.cn/img_convert/35fc46df24091ce3c9a5032a9919b755.jpeg)


#### 面试题


归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值