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,表示第一个CLD
    ClassLoaderDataGraph::_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为mtSymbol
    class SymbolTable : public RehashableHashtable<Symbol*, mtSymbol> 
StringTable类的定义:
    // 模板类,key为oop,value为mtSymbol
    class 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 = 360K
    initialize_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);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/323092.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

.Net6使用SignalR实现前后端实时通信

代码部分 后端代码 &#xff08;Asp.net core web api&#xff0c;用的.net6&#xff09;Program.cs 代码运行逻辑&#xff1a; ​1. 通过 WebApplication.CreateBuilder(args) 创建一个 ASP.NET Core 应用程序建造器。 2. 使用 builder.Services.AddControllers() 添加 MVC 控…

JavaScript之函数、数组作业

1.计算用户指定的数值内的奇数和&#xff0c;例如用户输入的是10&#xff0c;则计算1 3 5 7 9的和&#xff1b; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content&qu…

Mr_HJ / form-generator项目学习-增加自定义的超融组件(二)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbacheng/n…

Docker镜像构建优化及上传

前言 Dockerfile 是一个文本格式的配置文件&#xff0c; 用户可以使用 Dockerfile 来快速创建自定义的镜像&#xff0c;另外&#xff0c;使 用 Dockerfile 去构建镜像好比使用 pom 去构建 maven 项目一样&#xff0c;有异曲同工之妙 一.Dockerfile镜像构建 1.Dockerfile基本…

数据库知识汇总之MySQL

目录 MySQL数据库特点MySQL下载MySQL配置文件初始化MySQL配置安装MySQL服务 启动MySQL服务登录数据库修改数据库登录密码MySQL错误代码1130 MySQL数据库特点 MySQL是一个开源关系型数据库管理系统(RDBMS)&#xff0c;由Oracle公司维护和开发。它使用SQL语言进行数据库管理和操…

Linux下安装Mysql8.0版本【保姆级】

&#x1f95a;今日鸡汤&#x1f95a; 等风来&#xff0c;不如追风去。 ——《一禅小和尚》 目录 &#x1f37f;1.Linux查看glibc版本 &#x1f9c2;2.mysql下载 &#x1f9c8;3.上传到指定目录 &#x1f953;4.解压并操作 &#x1f32d;5.启动mysql 1.Linux查看glibc版本…

腾讯实验平台基于 StarRocks 构建湖仓底座

作者&#xff1a; 腾讯大数据平台部科学实验中心Tech Lead、专家工程师 马金勇博士 腾讯大数据平台部科学实验中心数据负责人、专家工程师 胡明杰 StarRocks Contributor、腾讯高级工程师 刘志行 在 2022 年&#xff0c;腾讯 A/B Test 团队启动了海外商业化版本 ABetterChoice …

常用文件文档能做二维码吗?多种文件在线做二维码的方法

二维码是现在工作和生活中随处可见&#xff0c;可以用来展现很多不同的内容。现在很多下发通知的文件、教程或者其他文件内容&#xff0c;也会制作成二维码图片后&#xff0c;让其他人通过扫码来获取文件内容。最简单的制作方法就是通过二维码生成器来制作&#xff0c;支持多种…

【Py/Java/C++三种语言详解】LeetCode每日一题240115【链表】LeetCode82、删除排序链表中的重复节点II

文章目录 题目链接题目描述解题思路代码pythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目链接 LeetCode82、删除排序链表中的重复节点II 题目描述 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不…

#AIGC##VDB# 【一篇入门VDB】矢量数据库-从技术介绍到选型方向

文章概览&#xff1a; 这篇文章深入探讨了矢量数据库的基本概念、工作原理以及在人工智能领域的广泛应用。 首先&#xff0c;文章解释了矢量的数学和物理学概念&#xff0c;然后引入了矢量在数据科学和机器学习中的应用。随后&#xff0c;详细介绍了什么是矢量数据库&#xff0…

【unity学习笔记】语音驱动blendershape

1.导入插件 https://assetstore.unity.com/packages/tools/animation/salsa-lipsync-suite-148442 1.选择小人&#xff0c;点击添加组件 分别加入组件&#xff1a; SALSA EmoteR Eyes Queue Processor&#xff08;必须加此脚本&#xff09;&#xff1a;控制前三个组件的脚本。…

基于深度学习的桃子熟度与大小智能检测

基于深度学习的桃子熟度与大小智能检测 基于深度学习的桃子熟度与大小智能检测引言1. 环境搭建与准备2. 数据准备3. 模型准备4. 训练准备5. 服务器端部署结语 基于深度学习的桃子熟度与大小智能检测 引言 随着时代的快速发展&#xff0c;人工智能时代为中国农业带来了新的机遇…

idea修改pom.xml没有重新导入maven的按钮

问题描述&#xff1a; IDEA修改pom.xml配置以后&#xff0c;不会展示 Load Maven Changes弹窗。 解决方法&#xff1a; 方式一、pom.xml右键&#xff0c;Maven--Run Maven--Reimport。但我感觉这个太麻烦了。 方式2、选择Building Tool Settings&#xff0c;点击Auto-Reload …

python -- str 字符串相减

从一个字符串中减去另一个字符串&#xff0c;得到一个新的字符串结果 replace() 方法 host_ip hello world host world ip host_ip.replace(host, "") print(ip)re.sub() 方法 import rehost_ip hello world host world ip re.sub(host, "", host_…

IDEA 启动错误提示:Command line is too long. Shorten command line

IDEA 启动错误提示&#xff1a;Command line is too long. Shorten command line Command line is too long. Shorten command line IDEA 启动错误提示&#xff1a;Command line is too long. Shorten command line快速修改原因解释 快速修改 Edit Configurations->configu…

IPv6路由综合运用

一、基础配置: SWA: sw1(config)#host swA swA(config)#ipv6 ena swA(config)# vlan 100 swA(config-vlan100)#int vlan 100 swA(config-if-vlan100)#ipv6 ena swA(config-vlan100)#ip add 172.16.1.1 255.255.255.252 swA(config-if-vlan100)#int e1/0/24 swA(conf…

C函数详解 | 函数的作用、定义与声明、函数的调用、函数与指针

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

生成式对抗网络GAN

Generative Adversarial Nets由伊恩古德费洛&#xff08;Ian J.Goodfellow&#xff09;等人于2014年发表在Conference on Neural Information Processing Systems (NeurIPS)上。NeurIPS是机器学习和计算神经科学领域的顶级国际学术会议之一。 1. GAN在哪些领域大放异彩 图像生…

远程访问及控制

文章目录 远程访问及控制一、SSH远程管理1、SSH&#xff08;Secure Shell&#xff09;协议定义2、SSH的优点3、OpenSSHell 二、配置OpenSSH服务端1、sshd_config配置文件的常用选项2、sshd服务支持的两种验证方式2.1 密码验证2.2 秘钥对验证 三、SSH客户端程序的使用1、基本用法…