java 线程执行原理,java线程在jvm中执行流程
java 线程执行原理,java线程在jvm中执行流程
从jvm视角看java线程执行过程
##首先thread.c注册jni函数
JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{(*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}
static JNINativeMethod methods[] = {{"start0", "()V", (void *)&JVM_StartThread},{"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},
};
##java Thread.java类start0 调用jni native方法
private native void start0();
##start0 调用jvm.cpp执行JVM_StartThread方法
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))JVMWrapper("JVM_StartThread");JavaThread *native_thread = NULL;// We cannot hold the Threads_lock when we throw an exception,// due to rank ordering issues. Example: we might need to grab the// Heap_lock while we construct the exception.bool throw_illegal_thread_state = false;// We must release the Threads_lock before we can post a jvmti event// in Thread::start.{// Ensure that the C++ Thread and OSThread structures aren't freed before// we operate.MutexLocker mu(Threads_lock);// Since JDK 5 the java.lang.Thread threadStatus is used to prevent// re-starting an already started thread, so we should usually find// that the JavaThread is null. However for a JNI attached thread// there is a small window between the Thread object being created// (with its JavaThread set) and the update to its threadStatus, so we// have to check for thisif (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {throw_illegal_thread_state = true;} else {// We could also check the stillborn flag to see if this thread was already stopped, but// for historical reasons we let the thread detect that itself when it starts runningjlong size =java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));// Allocate the C++ Thread structure and create the native thread. The// stack size retrieved from java is 64-bit signed, but the constructor takes// size_t (an unsigned type), which may be 32 or 64-bit depending on the platform.// - Avoid truncating on 32-bit platforms if size is greater than UINT_MAX.// - Avoid passing negative values which would result in really large stacks.NOT_LP64(if (size > SIZE_MAX) size = SIZE_MAX;)size_t sz = size > 0 ? (size_t) size : 0;native_thread = new JavaThread(&thread_entry, sz);// At this point it may be possible that no osthread was created for the// JavaThread due to lack of memory. Check for this situation and throw// an exception if necessary. Eventually we may want to change this so// that we only grab the lock if the thread was created successfully -// then we can also do this check and throw the exception in the// JavaThread constructor.if (native_thread->osthread() != NULL) {// Note: the current thread is not being used within "prepare".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) {ResourceMark rm(thread);log_warning(os, thread)("Failed to start the native thread for java.lang.Thread \"%s\"",JavaThread::name_for(JNIHandles::resolve_non_null(jthread)));// No one should hold a reference to the 'native_thread'.native_thread->smr_delete();if (JvmtiExport::should_post_resource_exhausted()) {JvmtiExport::post_resource_exhausted(JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,os::native_thread_creation_failed_msg());}THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),os::native_thread_creation_failed_msg());}#if INCLUDE_JFRif (JfrRecorder::is_recording() && EventThreadStart::is_enabled() &&EventThreadStart::is_stacktrace_enabled()) {JfrThreadLocal* tl = native_thread->jfr_thread_local();// skip Thread.start() and Thread.start0()tl->set_cached_stack_trace_id(JfrStackTraceRepository::record(thread, 2));}
#endifThread::start(native_thread);JVM_END
##创建线程
native_thread = new JavaThread(&thread_entry, sz);
##系统调用创建线程 os::create_thread(this, thr_type, stack_sz);
ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :Thread() {initialize();_jni_attach_state = _not_attaching_via_jni;set_entry_point(entry_point);// Create the native thread itself.// %note runtime_23os::ThreadType thr_type = os::java_thread;thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread :os::java_thread;os::create_thread(this, thr_type, stack_sz);// The _osthread may be NULL here because we ran out of memory (too many threads active).// We need to throw and OutOfMemoryError - however we cannot do this here because the caller// may hold a lock and all locks must be unlocked before throwing the exception (throwing// the exception consists of creating the exception object & initializing it, initialization// will leave the VM via a JavaCall and then all locks must be unlocked).//// The thread is still suspended when we reach here. Thread must be explicit started// by creator! Furthermore, the thread must also explicitly be added to the Threads list// by calling Threads:add. The reason why this is not done here, is because the thread// object must be fully initialized (take a look at JVM_Start)
}
bool os::create_thread(Thread* thread, ThreadType thr_type,size_t req_stack_size) {assert(thread->osthread() == NULL, "caller responsible");// Allocate the OSThread object.OSThread* osthread = new OSThread(NULL, NULL);if (osthread == NULL) {return false;}// Set the correct thread state.osthread->set_thread_type(thr_type);// Initial state is ALLOCATED but not INITIALIZEDosthread->set_state(ALLOCATED);thread->set_osthread(osthread);// Init thread attributes.pthread_attr_t attr;pthread_attr_init(&attr);guarantee(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0, "???");// Make sure we run in 1:1 kernel-user-thread mode.if (os::Aix::on_aix()) {guarantee(pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) == 0, "???");guarantee(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0, "???");}// Start in suspended state, and in os::thread_start, wake the thread up.guarantee(pthread_attr_setsuspendstate_np(&attr, PTHREAD_CREATE_SUSPENDED_NP) == 0, "???");// Calculate stack size if it's not specified by caller.size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);// JDK-8187028: It was observed that on some configurations (4K backed thread stacks)// the real thread stack size may be smaller than the requested stack size, by as much as 64K.// This very much looks like a pthread lib error. As a workaround, increase the stack size// by 64K for small thread stacks (arbitrarily choosen to be < 4MB)if (stack_size < 4096 * K) {stack_size += 64 * K;}// On Aix, pthread_attr_setstacksize fails with huge values and leaves the// thread size in attr unchanged. If this is the minimal stack size as set// by pthread_attr_init this leads to crashes after thread creation. E.g. the// guard pages might not fit on the tiny stack created.int ret = pthread_attr_setstacksize(&attr, stack_size);if (ret != 0) {log_warning(os, thread)("The %sthread stack size specified is invalid: " SIZE_FORMAT "k",(thr_type == compiler_thread) ? "compiler " : ((thr_type == java_thread) ? "" : "VM "),stack_size / K);thread->set_osthread(NULL);delete osthread;return false;}// Save some cycles and a page by disabling OS guard pages where we have our own// VM guard pages (in java threads). For other threads, keep system default guard// pages in place.if (thr_type == java_thread || thr_type == compiler_thread) {ret = pthread_attr_setguardsize(&attr, 0);}ResourceMark rm;pthread_t tid = 0;if (ret == 0) {int limit = 3;do {ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);} while (ret == EAGAIN && limit-- > 0);}if (ret == 0) {char buf[64];log_info(os, thread)("Thread \"%s\" started (pthread id: " UINTX_FORMAT ", attributes: %s). ",thread->name(), (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));} else {char buf[64];log_warning(os, thread)("Failed to start thread \"%s\" - pthread_create failed (%d=%s) for attributes: %s.",thread->name(), ret, os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));// Log some OS information which might explain why creating the thread failed.log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());LogStream st(Log(os, thread)::info());os::Posix::print_rlimit_info(&st);os::print_memory_info(&st);}pthread_attr_destroy(&attr);if (ret != 0) {// Need to clean up stuff we've allocated so far.thread->set_osthread(NULL);delete osthread;return false;}// OSThread::thread_id is the pthread id.osthread->set_thread_id(tid);return true;
}
##通过函数回调thread_entry方法
native_thread = new JavaThread(&thread_entry, sz);
static void thread_entry(JavaThread* thread, TRAPS) {HandleMark hm(THREAD);Handle obj(THREAD, thread->threadObj());JavaValue result(T_VOID);JavaCalls::call_virtual(&result,obj,SystemDictionary::Thread_klass(),vmSymbols::run_method_name(),vmSymbols::void_method_signature(),THREAD);
}
##call_virtual 执行java run方法
相关文章:
java 线程执行原理,java线程在jvm中执行流程
java 线程执行原理,java线程在jvm中执行流程 从jvm视角看java线程执行过程 ##首先thread.c注册jni函数 JNIEXPORT void JNICALL Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls) {(*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(…...
[Redis]基本全局命令
Redis存储方式介绍 在 Redis 中数据是以键值对的凡事存储的,键(Key)和值(Value)是基本的数据存储单元。以下是对 Redis 键值对的详细讲解: 键(Key): 类型:…...
【Linux】- HBase集群部署 [19]
简介 apache HBase是一种分布式、可扩展、支持海量数据存储的 NoSQL 数据库。 和Redis一样,HBase是一款KeyValue型存储的数据库。 不过和Redis涉及方向不同 Redis设计为少量数据,超快检索HBase设计为海量数据,快速检索 HBase在大数据邻域…...
js如何遍历FormData的值
遍历FormData的值,一般有2种方法:forEach 和 for...of entries const data new FormData();data.append(aaa, 111); data.append(bbb, 222);// 方法1 data.forEach((value, key) > {console.log(key, value); }) 输出 aaa 111 和 bbb 222// 方法2 …...
【C语言】明析部分C语言内存函数
目录 1.memcpy 2.memmove 3.memset 4.memcmp 以下都是内存函数,作用单位均是字节 1.memcpy memcpy是C/C语言中的一个内存拷贝函数,其原型为: void* memcpy(void* dest, const void* src, size_t n);目标空间(字节)…...
一阶数字高通滤波器
本文的主要内容包含一阶高通滤波器公式的推导和数字算法的实现以及编程和仿真 1 计算公式推导 1.1.2 算法实现及仿真 利用python实现的代码如下: import numpy as np # from scipy.signal import butter, lfilter, freqz import matplotlib.pyplot as plt #2pifW…...
Linux多线程系列2: 模拟封装简易语言级线程库,线程互斥和锁,线程同步和条件变量,线程其他知识点
Linux多线程系列2: 模拟封装简易语言级线程库,线程互斥和互斥锁,线程同步和条件变量,线程其他知识点 1.前言 一.模拟C11线程库自己封装简易语言级线程库1.实现框架2.迅速把构造等等函数写完3.start和work1.尝试一2.尝试二3.最终版本4.给出代码 二.模拟实现多线程(为编写线程池做…...
VUE3-form表单保存附件与基本信息
element-ui代码 <el-dialog :title"上传附件" v-model"dialogAdds.visible" width"500px" append-to-body> <el-form-item label"唯一标识"> <dict-tag v-if"form.groupId" :options"unique_identifica…...
无线网络安全技术基础
无线网络安全技术基础 无线网络安全风险和隐患 随着无线网络技术广泛应用,其安全性越来越引起关注.无线网络的安全主要有访问控制和数据加密,访问控制保证机密数据只能由授权用户访问,而数据加密则要求发送的数据只能被授权用户所接受和使用。 无线网络在数据传输时以微波进…...
sheng的学习笔记-docker部署Greenplum
目录 docker安装gp数据库 mac版本 搭建gp数据库 连接数据库 windows版本 搭建gp数据库 连接数据库 docker安装gp数据库 mac版本 搭建gp数据库 打开终端,输入代码,查看版本 ocker search greenplum docker pull projectairws/greenplum docker…...
【投稿资讯】区块链会议CCF A -- SP 2025 截止6.6、11.14 附录用率
会议名称:46th IEEE Symposium on Security and Privacy( S&P) CCF等级:CCF A类学术会议 类别:网络与信息安全 录用率:2023年 195/1147,2024年录用了17篇和区块链相关的论文 Topics of interest inc…...
C++哪些函数不能被声明为虚函数
在C中,某些函数不能被声明为虚函数。下面详细解释哪些函数不能被声明为虚函数,并通过代码示例进行说明。 C哪些函数不能被声明为虚函数 不能声明为虚函数的函数示例代码及解释一、构造函数不能是虚函数二、静态成员函数不能是虚函数三、友元函数不能是虚…...
vue中数据已经改变了,但是table里面内容没更新渲染!
解决方案: 给table或者el-table标签上添加一个动态key值,只要数据发生改变,key值变动一下即可 标签上: :key“timeStamp” 初始data:timeStamp:0, 更新数据:this.timeStamp 这样每次更新数据ÿ…...
头歌实践教学平台:Junit实训入门篇
第2关:Junit注解 任务描述 给出一个带有注解的Junit代码及其代码打印输出,要求学员修改注解位置,让输出结果变为逆序。 相关知识 Junit注解 Java注解((Annotation)的使用方法是" 注解名" 。借助注解&a…...
matlab使用教程(80)—修改图形对象的透明度
1.更改图像、填充或曲面的透明度 此示例说明如何修改图像、填充或曲面的透明度。 1.1坐标区框中所有对象的透明度 透明度值称为 alpha 值。使用 alpha 函数设置当前坐标区范围内所有图像、填充或曲面对象的透明度。指定一个介于 0(完全透明)和 1&#x…...
mysql bin 日志转成sql
首先确定mysql binlog 服务开启 SHOW VARIABLES LIKE log_bin; 找到binlog日志 find / -name mysql-bin.* -type f 下载下来 本地找到mysql安装位置的bin目录 在窗口路径处直接输入cmd 执行 mysqlbinlog --no-defaults --base64-outputdecode-rows -v --start-datetime&…...
河南道路与桥梁乙级资质申请:注册证书与职称证书准备
在河南道路与桥梁乙级资质申请中,注册证书与职称证书的准备是不可或缺的环节。以下是关于如何准备这些证书的一些关键步骤和要点: 明确所需证书类型: 注册证书:这通常指的是相关专业的注册工程师证书,如注册土木工程师…...
3D工业视觉
前言 本文主要介绍3D视觉技术、工业领域的应用、市场格局等,主要技术包括激光三角测量、结构光、ToF、立体视觉。 一、核心内容 3D视觉技术满足工业领域更高精度、更高速度、更柔性化的需求,扩大工业自动化的场景。 2D视觉技术基于物体平面轮廓&#…...
使用auth_basic模块进行基础认证
在建立和维护Web服务器时,身份认证是一个至关重要的环节。Nginx作为一个高性能的Web服务器,支持许多认证方法,其中较为简单和常用的一种即是基础身份认证(Basic Authentication),这需要借助auth_basic模块实…...
深度解析物联网平台:优化数据点位管理的实战策略
策略管理 策略,作为在物联网平台数据点位创建过程中可设定的规则,涵盖了多个重要方面,策略是在创建点位的时候,可以设置的规则,包括存储策略、告警策略、通知策略以及联动策略。这些策略都是通过专门的列表页面进行集…...
AI原生软件容灾设计避坑指南(2024最新Gartner认证框架实操版)
第一章:AI原生软件容灾设计的核心范式演进 2026奇点智能技术大会(https://ml-summit.org) 传统容灾体系面向确定性状态机与静态服务拓扑构建,而AI原生软件——尤其是以LLM推理服务、实时微调管道、向量检索集群为代表的新型负载——其核心特征在于动态权…...
Android高级开发工程师(KTV领域)技术深度解析与面试指南
前言:KTV应用开发的独特挑战与价值 在移动互联网深入发展的今天,KTV娱乐体验也逐渐向线上化和智能化转型。作为Android应用高级开发工程师,投身于KTV相关产品的开发与维护,意味着需要面对一系列独特的技术挑战: 实时性与低延迟: 歌唱对音频的实时同步要求极高,任何明显…...
OBS Multi RTMP插件:免费开源的多平台直播终极解决方案
OBS Multi RTMP插件:免费开源的多平台直播终极解决方案 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 想要实现多平台直播却苦于繁琐的操作流程?OBS Multi RTMP…...
告别‘玄学’听诊:我是如何用Python和CNN-LSTM模型给心音‘打分’的(准确率92%)
告别‘玄学’听诊:我是如何用Python和CNN-LSTM模型给心音‘打分’的(准确率92%) 作为一名长期在医疗AI领域摸爬滚打的数据科学家,我始终被一个问题困扰:为什么21世纪的心脏听诊依然像中世纪占星术一样依赖"经验之…...
Java Loom + R2DBC + VirtualThread三重奏:构建零阻塞数据库访问层(含GraalVM原生镜像适配方案)
第一章:Java Loom响应式编程转型的背景与核心价值长期以来,Java 的并发模型依赖线程(Thread)作为基本执行单元,但传统线程是重量级操作系统资源,受限于内核调度开销与内存占用(每个线程栈默认 1…...
模型加载失败怎么办?Qwen3-4B-Instruct-2507排错流程图解
模型加载失败怎么办?Qwen3-4B-Instruct-2507排错流程图解 1. 问题排查思路与流程 当你使用vllm部署Qwen3-4B-Instruct-2507模型并遇到加载失败问题时,可以按照以下流程图进行系统排查: graph TDA[模型加载失败] --> B{检查模型服务状态…...
【Shell专项】数组与函数的使用
第四章 数组和函数4.1 数组 4.1.1 简介 变量:用一个固定的字符串,代替一个不固定字符串。数组:用一个固定的字符串,代替多个不固定字符串。 4.1.2 类型 普通数组:只能使用整数作为数组索引关联数组:可以使用…...
1000+ 道 Java面试题及答案整理(牛客网最新版)
作为 Java 程序员,选择学习什么样的技术?什么技术该不该学?去招聘网站上搜一搜、看看岗位要求就十分清楚了,自己具备的技术和能力,直接影响到你工作选择范围和能不能面试成功。 如果想进大厂,那就需要在 Ja…...
AI时代新型的项目管理应该是什么样的?侣
AI训练存储选型的演进路线 第一阶段:单机直连时代 早期的深度学习数据集较小,模型训练通常在单台服务器或单张GPU卡上完成。此时直接将数据存储在训练机器的本地NVMe SSD/HDD上。 其优势在于IO延迟最低,吞吐量极高,也就是“数据离…...
时间序列平稳性:从理论到实战检验指南
1. 为什么时间序列需要平稳性? 想象一下你每天记录体重变化。如果体重在60kg上下小幅波动(比如59.5kg到60.5kg),我们很容易预测明天的体重大概率也在60kg附近。但如果体重每周增加1kg(从60kg持续增长到70kg)…...
