JVM学习 : VM_Thread
代码图片来自:https://blog.csdn.net/qq_31865983/article/details/103788358
VM_Thread 就是大家平时说的 JVM线程,只有一个实例,也就是虚拟机创建过程中只会被创建一次(C++层面),并且在虚拟机销毁的时候被销毁
具体的作用是 开启一个无限循环(while (true)), 然后不断地从一个 VM_Operation 队列中取出 VM_Operation 并且执行,如果没有 VM_Operation 就等待一会
VM_Operation 是通过其他线程 放入到队列中的,所以类似 生产者-消费者 模式。VM_Operation 有许多种,大概有四类
从注释上看,应该都是一些堆内存的分配操作?
细分的话,具体操作如下:
#define VM_OP_ENUM(type) VMOp_##type,
// Note: When new VM_XXX comes up, add 'XXX' to the template table.
#define VM_OPS_DO(template)
template(Dummy)
template(ThreadStop)
template(ThreadDump)
template(PrintThreads)
template(FindDeadlocks)
template(ForceSafepoint)
template(ForceAsyncSafepoint)
template(Deoptimize)
template(DeoptimizeFrame)
template(DeoptimizeAll)
template(ZombieAll)
template(UnlinkSymbols)
template(Verify)
template(PrintJNI)
template(HeapDumper)
template(DeoptimizeTheWorld)
template(CollectForMetadataAllocation)
template(GC_HeapInspection)
template(GenCollectFull)
template(GenCollectFullConcurrent)
template(GenCollectForAllocation)
template(ParallelGCFailedAllocation)
template(ParallelGCSystemGC)
template(CGC_Operation)
template(CMS_Initial_Mark)
template(CMS_Final_Remark)
template(G1CollectFull)
template(G1CollectForAllocation)
template(G1IncCollectionPause)
template(DestroyAllocationContext)
template(EnableBiasedLocking)
template(RevokeBias)
template(BulkRevokeBias)
template(PopulateDumpSharedSpace)
template(JNIFunctionTableCopier)
template(RedefineClasses)
template(GetOwnedMonitorInfo)
template(GetObjectMonitorUsage)
template(GetCurrentContendedMonitor)
template(GetStackTrace)
template(GetMultipleStackTraces)
template(GetAllStackTraces)
template(GetThreadListStackTraces)
template(GetFrameCount)
template(GetFrameLocation)
template(ChangeBreakpoints)
template(GetOrSetLocal)
template(GetCurrentLocation)
template(EnterInterpOnlyMode)
template(ChangeSingleStep)
template(HeapWalkOperation)
template(HeapIterateOperation)
template(ReportJavaOutOfMemory)
template(JFRCheckpoint)
template(Exit)
template(LinuxDllLoad)
template(RotateGCLog)
template(WhiteBoxOperation)
template(ClassLoaderStatsOperation)
比较值得注意的是 加载Linux 的 动态链接库:
比较重要的就是GC操作:
每个线程通过 VMThread::execute 把 VM_Operation 放入队列的之前会通过doit_prologue方法做检查,检查是否能把这个 VM_Operation 放入队列。
因为VM_Operation有可能会被多个Java线程入队,但是实际上只用一个入队就够了。
有一种比较典型的情况就是GC操作可能会被多个Java线程入队,但实际只用GC一次就够了。
实际执行 VM_Operation 是在 VM_Operation::evaluate 中
具体过程伪代码:
Java方法投递该VM_operation
VMThread::execute (VM_Operation op)
不是 VM_Thread来执行投递方法:
if (op::doit_prologue()) {
enqueue(op);
op::doit_epilogue();
}
如果是VM_Thread的话,可以直接执行evaluate方法
void VMThread::execute(VM_Operation* op) {
Thread* t = Thread::current();
if (!t->is_VM_thread()) {
SkipGCALot sgcalot(t); // avoid re-entrant attempts to gc-a-lot
// JavaThread or WatcherThread
bool concurrent = op->evaluate_concurrently();
// only blocking VM operations need to verify the caller's safepoint state:
if (!concurrent) {
t->check_for_valid_safepoint_state(true);
}
// New request from Java thread, evaluate prologue
if (!op->doit_prologue()) {
return; // op was cancelled
}
// Setup VM_operations for execution
op->set_calling_thread(t, Thread::get_priority(t));
// It does not make sense to execute the epilogue, if the VM operation object is getting
// deallocated by the VM thread.
bool execute_epilog = !op->is_cheap_allocated();
assert(!concurrent || op->is_cheap_allocated(), "concurrent => cheap_allocated");
// Get ticket number for non-concurrent VM operations
int ticket = 0;
if (!concurrent) {
ticket = t->vm_operation_ticket();
}
// Add VM operation to list of waiting threads. We are guaranteed not to block while holding the
// VMOperationQueue_lock, so we can block without a safepoint check. This allows vm operation requests
// to be queued up during a safepoint synchronization.
{
VMOperationQueue_lock->lock_without_safepoint_check();
bool ok = _vm_queue->add(op);
op->set_timestamp(os::javaTimeMillis());
VMOperationQueue_lock->notify();
VMOperationQueue_lock->unlock();
// VM_Operation got skipped
if (!ok) {
assert(concurrent, "can only skip concurrent tasks");
if (op->is_cheap_allocated()) delete op;
return;
}
}
if (!concurrent) {
// Wait for completion of request (non-concurrent)
// Note: only a JavaThread triggers the safepoint check when locking
MutexLocker mu(VMOperationRequest_lock);
while(t->vm_operation_completed_count() < ticket) {
VMOperationRequest_lock->wait(!t->is_Java_thread());
}
}
if (execute_epilog) {
op->doit_epilogue();
}
} else {
// invoked by VM thread; usually nested VM operation
assert(t->is_VM_thread(), "must be a VM thread");
VM_Operation* prev_vm_operation = vm_operation();
if (prev_vm_operation != NULL) {
// Check the VM operation allows nested VM operation. This normally not the case, e.g., the compiler
// does not allow nested scavenges or compiles.
if (!prev_vm_operation->allow_nested_vm_operations()) {
fatal(err_msg("Nested VM operation %s requested by operation %s",
op->name(), vm_operation()->name()));
}
op->set_calling_thread(prev_vm_operation->calling_thread(), prev_vm_operation->priority());
}
EventMark em("Executing %s VM operation: %s", prev_vm_operation ? "nested" : "", op->name());
// Release all internal handles after operation is evaluated
HandleMark hm(t);
_cur_vm_operation = op;
if (op->evaluate_at_safepoint() && !SafepointSynchronize::is_at_safepoint()) {
SafepointSynchronize::begin();
op->evaluate();
SafepointSynchronize::end();
} else {
op->evaluate();
}
// Free memory if needed
if (op->is_cheap_allocated()) delete op;
_cur_vm_operation = prev_vm_operation;
}
}
进入队列之后的 op 们,会在 VM_Thread run方法 的 loop 循环中被取出执行,当然,这个队列被取出时要加锁 MutexLockerEx(具体通过pthread_cond_wait等pthread库函数实现)
run方法是在新的操作系统线程中执行的。
具体在Threads::create_vm中体现:
具体os是怎么开始run方法的?
起始是有一个 叫 java_start 的方法,调用了 run 方法
然后 os_start 调用 pthread_start 创建一个操作系统层面的线程去执行 java_start
- R语言可视化——REmap(路径图)
- python面向对象
- 字符串hash入门
- R语言数据处理——数据合并与追加
- python爬取链家租房之获取房屋页面的详细信息(房名,地址,房价,面积,url)
- 信用卡“坏账”客户分析(二)
- Mac上提升python运算速度-PyPy初体验
- python处理json数据(复杂的json转化成嵌套字典并处理)
- Pointer-network理论及tensorflow实战
- python3 log文件处理获取某天需要的数据
- 实战深度强化学习DQN-理论和实践
- Python 工匠:编写条件分支代码的技巧
- python3 下 Zabbix监控调用graph.get并且下载监控图
- 用R语言复盘美国总统大选结果~
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- java实现多个网络文件批量下载并压缩
- Python学习笔记(四) 爬取网站数据(静态,动态)
- java整合FastDFS文件服务器
- Flutter基础widgets教程-CupertinoSwitch篇
- XmlRootElement的作用和用法
- 获取指定月份的所有工作日(工作日为自定义的)
- 自定义配置类,读取Application.properties中的参数
- 将InputSteram转换成文件输出并下载至本地
- sql serve2008是否自带互斥锁
- Flutter基础widgets教程-CupertinoSwitch篇
- Flutter基础widgets教程-CupertinoTabScaffold篇
- C++11 move 语义
- 论函数的设计应如何才好,返回临时变量 | 返回引用 | 传递引用
- Flutter基础widgets教程-CupertinoTabView篇
- 关于time的使用