Hotspot源码解析-第十九章-ClassLoaderData、符号表、字符串表的初始化
第十九章-ClassLoaderData初始化
讲解本章先从一张图开始
众所周知,Java类的相关信息都是存储在元空间中的,但是是怎么存储的,相信很多读者是不清楚的,这里就不得不涉及到ClassLoaderDataGraph、classLoader、classLoaderData(简称CLD)和Klass的概念及他们四者的关系,这里简单描述下他们的概念,具体细节放到类加载器那一张来讲解。
InstanceKlass(继承自Klass):每个被加载的类在虚拟机中的表示为一个InstanceKlass
ClassLoaderData:类加载器加载类后,存储数据的对象,也就是说被加载的类最终都存储在ClassLoaderData指向的地方,一个CLD可以存入很多被加载的类InstanceKlass,多个InstanceKlass之间通过链表形式存储,且链表头永远是最新加载的类
ClassLoader:类加载器,每个ClassLoader都有一个CLD
ClassLoaderDataGraph:这是CLD的总入口,把所有CLD通过链表管理起来
19.1 根加载器CLD的创建
19.1.1 universe.cpp
19.1.1.1 ClassLoaderData::init_null_class_loader_data
static void init_null_class_loader_data() {// 验证重复初始化assert(_the_null_class_loader_data == NULL, "cannot initialize twice");assert(ClassLoaderDataGraph::_head == NULL, "cannot initialize twice");// 创建ClassLoaderData对象,第一个加载器的参数是NULL,因为在Java中,没有对根加载器的实现,这个是由虚拟机自身来实现加载的,所以相对Java,这是一个NULL,实现看`章节19.1.2`_the_null_class_loader_data = new ClassLoaderData((oop)NULL, false, Dependencies());// 创建完后,赋值给ClassLoaderDataGraph::_head,表示第一个CLDClassLoaderDataGraph::_head = _the_null_class_loader_data;assert(_the_null_class_loader_data->is_the_null_class_loader_data(), "Must be");if (DumpSharedSpaces) { // 不涉及多Java进程共享,这一步不会走_the_null_class_loader_data->initialize_shared_metaspaces();}}
19.1.2 classLoaderData.cpp
19.1.2.1 ClassLoaderData构造函数
发现这个构造函数,啥也没做,就是对字段赋初始值
ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies) :_class_loader(h_class_loader()),_is_anonymous(is_anonymous),// An anonymous class loader data doesn't have anything to keep// it from being unloaded during parsing of the anonymous class.// The null-class-loader should always be kept alive._keep_alive(is_anonymous || h_class_loader.is_null()),_metaspace(NULL), _unloading(false), _klasses(NULL),_claimed(0), _jmethod_ids(NULL), _handles(), _deallocate_list(NULL),_next(NULL), _dependencies(dependencies),_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) {JFR_ONLY(INIT_ID(this);)
}
19.2 符号表和字符串表
先了解下什么是符号表,什么是字符串表?
SymbolTable(符号表):符号是指字节码中产生的各种元数据的utf-8字符表示,所以符号表就是用来存放这些utf-8字符的
StringTable(字符串表):就是存放Java中String对象的,把StringTable表中的数据都可以想像成与Java中String对应
先这么理解吧,在类加载器那一章节会更细致的讲这两个概念。
以下是函数的部分内容,该函数是universe.cpp->universe_init()
// 创建符号表,把它想像成java里的HashMap
SymbolTable::create_table();
// 创建字符串表,把它想像成java里的HashMap
StringTable::create_table();
// 创建包信息表,也可以想像成一个HashMap,包信息用到的时候再讲
ClassLoader::create_package_info_table();SymbolTable类的定义:// 模板类,key为Symbol,value为mtSymbolclass SymbolTable : public RehashableHashtable<Symbol*, mtSymbol>
StringTable类的定义:// 模板类,key为oop,value为mtSymbolclass StringTable : public RehashableHashtable<oop, mtSymbol> SymbolTable:key是Symbol,Symbol可以理解为utf8编码的字符信息
SymbolTable:value是mtSymbol,这是一个枚举值,仅仅表示内存的类型解释,不起实际作用StringTable:key是oop,oop可以理解为指向Java对象的地址(实际上存放的就是Java的String对象的地址)
StringTable:value是mtSymbol,这是一个枚举值,仅仅表示内存的类型解释,不起实际作用
两个表的创建过程都非常简单,但是符号表SymbolTable的创建要复杂些,增加了initialize_symbols初始化符号的操作,代码如下:
static void create_table() {assert(_the_table == NULL, "One symbol table allowed.");_the_table = new SymbolTable();// 预先创建并分配存放符号的内存chunk,symbol_alloc_arena_size = 360Kinitialize_symbols(symbol_alloc_arena_size);}void SymbolTable::initialize_symbols(int arena_alloc_size) {// Initialize the arena for global symbols, size passed in depends on CDS.if (arena_alloc_size == 0) {_arena = new (mtSymbol) Arena(mtSymbol);} else {// 创建一个Arena对象,细节看`章节19.2.1`_arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size);}
}
19.2.1 allocation.cpp
19.2.1.1 Arena构造函数
在JVM运行过程中,会产生大量的符号,为了效率在存储时不可能来一个分配一个,所以需要提前划出一片区域chunk来存储,如果一块chunk不够了,再创建一块,依此类推,Arena就是管理这些chunk的类对象,各chunk之间以链表的形式关联,整个JVM中对内存的管理中,大量使用链表这一数据结构来处理。顺便描述下Arena的几个字段的含义
Chunk *_first; // 第一块 chunk
Chunk *_chunk; // 前在用的 chunk
char *_hwm, *_max; // 当前在用的 chunk 起始点和限制点
size_t _size_in_bytes; // Arena的总大小(所有chunk大小相加)
Arena::Arena(MEMFLAGS flag, size_t init_size) : _flags(flag), _size_in_bytes(0) {size_t round_size = (sizeof (char *)) - 1;init_size = (init_size+round_size) & ~round_size;// 主要看这里,创建了一个init_size大小的chunk块_first = _chunk = new (AllocFailStrategy::EXIT_OOM, init_size) Chunk(init_size);_hwm = _chunk->bottom(); // 保存 hwm, max,分别指向chunk块可操作的起始点和限制点_max = _chunk->top();MemTracker::record_new_arena(flag);set_size_in_bytes(init_size);
}
相关文章:

Hotspot源码解析-第十九章-ClassLoaderData、符号表、字符串表的初始化
第十九章-ClassLoaderData初始化 讲解本章先从一张图开始 众所周知,Java类的相关信息都是存储在元空间中的,但是是怎么存储的,相信很多读者是不清楚的,这里就不得不涉及到ClassLoaderDataGraph、classLoader、classLoaderData&…...

impala元数据自动刷新
一.操作步骤 进入CM界面 > Hive > 配置 > 搜索 启用数据库中的存储通知(英文界面搜索:Enable Stored Notifications in Database),并且勾选,注意一定要勾选,配置后面的配置不生效。数据库通知的保留时间默认为2天&#…...
骑砍战团MOD开发(35)-射击精度系统
一.射击精度 和CF等FPS射击类游戏一样,为了模拟实际射击过程中弓箭,子弹等投掷物的射击偏移,故设计精度系统控制不同武器不同兵种的使用武器能力,统称为游戏精度系统. 由于骑砍可以在马上进行射击,故引擎内部也内置了骑射技能点以便控制玩家在骑马过程中射击的能力. 武器精度:通…...

树莓派非常实用的程序-3 vcdbg
vcdbg 是一个应用程序,用于帮助从在ARM上运行的Linux调试VideoCore GPU。它需要以根用户身份运行。此应用程序主要用于Raspberry Pi工程师,尽管有一些命令一般用户可能会发现有用。 sudo vcdbg help 将给出可用命令的列表。 NOTE 仅列出了最终用户使用…...

jmeter分布式服务搭建
目录 一、环境准备 二、 安装包下载 三 、安装jdk 四 、控制机安装 4.1 解压压缩包 4.2 修改 bin/jmeter.properties 4.3 修改 bin/system.properties 五、执行机安装 5.1 解压安装包 5.2 修改 bin/jmeter.properties 5.3 修改 bin/system.properties 5.4 启动执行机 …...

vue中el-radio无法默认选中
页面上不生效,默认什么都不选中 <el-radio-group v-model"queryParams.videoUrlType"><el-radio :label"1">本地上传</el-radio><el-radio :label"2">外部链接</el-radio> </el-radio-group>da…...

分布式I/O应用于智慧停车场的方案介绍
客户案例背景 目前车位检测技术有磁电技术、超声波技术、红外线技术、图像识别车位技术。考虑到例如电磁干扰、信号干扰等的环境因素影响,通常会采用组合使用的方式进行,如采用不同的传感器、应用不同的协议等,以便提高车位检测的准确性和实时…...
node后端+vue前端实现接口请求时携带authorization验证
node后端vue前端实现接口请求时携带authorization验证 我们在写web项目时,后端写好接口,前端想要调用后端接口时,除了登录注册页面,所有的请求都需要携带authorization,这样是为了避免随意通过接口调取数据的现象发生…...
SourceTree管理git
SourceTree管理git...

【数模百科】一篇文章讲清楚灰色预测模型GM(1,1)附python代码
本篇文章摘录自GM(1,1) - 数模百科 ,如果想了解更多有关灰色预测模型的信息,请移步 灰色预测模型 - 数模百科 首先,“灰色”这个词在这里不是指颜色,而是形容一种信息状态,介于黑(信息全无)和白…...
openssl3.2 - 官方demo学习 - mac - hmac-sha512.c
文章目录 openssl3.2 - 官方demo学习 - mac - hmac-sha512.c概述笔记END openssl3.2 - 官方demo学习 - mac - hmac-sha512.c 概述 MAC算法为HMAC, 设置参数(摘要算法为SHA3-512), 用key初始化, 对明文做MAC数据. 笔记 /*! \file hmac-sha512.c \note openssl3.2 - 官方demo…...

pycharm的使用技巧
1.新建文件时,自动生成代码 settings->editor->file and code templates,选择python script ${NAME} 文件名 ${DATE} 日期 2.自动补齐自定义段落 settings->editor->live templates,在右侧点击+号,添加自定义的内容 完成之后,在下方勾选python 3.修改注释的…...

如何通过内网穿透实现公网访问Portainer管理监控Docker容器
文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 正文开始前给大家推荐个网站,前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风…...

Redis原理篇(Dict的收缩扩容机制和渐进式rehash)
Dict(即字典) Redis是一种键值型数据库,其中键与值的映射关系就是Dict实现的。 Dict通过三部分组成:哈希表(DictHashTable),哈希节点(DictEntry),字典(Dict)…...

Microsoft Remote Desktop for Mac 中文正式版下载 微软远程连接软件
Microsoft Remote Desktop 是一款专为 Mac 用户设计的远程桌面工具,它可以帮助用户通过网络连接到其他计算机,实现远程控制和操作。 软件下载:Microsoft Remote Desktop for Mac 中文正式版下载 该工具支持多种远程连接协议,包括 …...
解读Vue的原型及原型链
在 JavaScript 中,每个对象都有一个关联的原型(prototype)。原型是一个对象,其他对象可以通过原型实现属性和方法的继承。原型链是一种由对象组成的链式结构,它通过原型的引用连接了一系列对象,形成了一种继…...
拓扑排序(优先队列)queue、C++
N个小朋友,编号 1∼N,要排成一队。在安排每个人的顺序时,有 M 个要求,每个要求包含两个整数 a,b,表示小朋友 a 要排在小朋友 b 的前面。 请你找出符合所有要求的排队顺序。 输入格式 第一行包含整数 N,M。接下来 M 行…...

【Spring】SpringBoot 统一功能处理
文章目录 前言1. 拦截器1.1 什么是拦截器1.2 拦截器的使用1.2.1 自定义拦截器1.2.2 注册配置拦截器 1.3 拦截器详解1.3.1 拦截路径1.3.2 拦截器执行流程1.3.3 适配器模式 2. 统一数据返回格式3. 统一异常处理 前言 在日常使用 Spring 框架进行开发的时候,对于一些板…...

拦截器HandlerInterceptor | springmvc系列
拦截器,通俗来来将,就是我们将访问某个路径的请求给拦截下来,然后可以对这个请求做一些操作 基本使用 创建拦截器类 让类实现HandlerInterceptor接口,重写接口中的三个方法。 Component //定义拦截器类,实现Handle…...
【SQL server】DML触发器监控数据库字段值改变
文章目录 前言DML触发器基本思路创建触发器固定字段触发示例完整示例代码变量声明查询新旧值插入数据到日志表效果视频动态字段触发示例完整代码示例触发器基本信息变量声明定义游标打开游标临时表创建循环处理字段...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...