JVM
文章平均质量分 78
阿达King哥
专注JVM原理分析
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
JVM openjdk原理和源码分析目录
逐步深入JVM核心原理原创 2025-11-07 16:24:23 · 478 阅读 · 0 评论
-
模板解释器
模板解释器概述 模板解释器是JVM中用于提升字节码执行效率的一种技术。它通过预先为每个字节码指令定义汇编实现模板,并将这些模板存储在模板表中。每个模板包含标志位、输入/输出栈顶状态、生成函数指针等属性。在初始化阶段,模板表会为所有字节码指令注册对应的模板实现。执行时,解释器直接调用相应字节码的预生成汇编代码,避免了switch-case带来的性能损耗。这种设计显著提高了字节码解释执行的效率,是JVM解释器实现的关键优化手段。原创 2026-04-09 15:08:47 · 231 阅读 · 0 评论 -
解释器指令入口——栈顶缓存
本文深入探讨了Java虚拟机中解释器指令执行的栈顶缓存机制。通过两个具体示例分析了栈顶状态对字节码执行的影响:当栈顶状态一致时直接更新寄存器,不一致时需进行压栈操作。文章详细介绍了HotSpot虚拟机如何通过模板表(TemplateTable)定义每个字节码的输入输出栈顶状态,并生成相应的汇编代码。栈顶缓存的本质是根据下一条指令的需求决定上一条指令结果存放位置(寄存器或内存),这种机制有效优化了解释器的执行效率。文章还通过NOP指令的极端案例展示了栈顶状态转换的实际应用。原创 2026-04-06 18:00:59 · 415 阅读 · 0 评论 -
解释器指令入口——转发表
HotSpot JVM采用转发表机制高效执行字节码指令,避免分支判断导致的流水线冲刷。转发表是一个二维表,行表示栈顶状态(如int、long等),列表示256个字节码指令。每个单元格存储对应指令的汇编实现入口地址。JVM初始化时通过set_entry_points_for_all_bytes()填充转发表,将各字节码指令的实现地址按栈顶状态分类存储。执行时,JVM通过dispatch_next从转发表快速查找当前栈顶状态下的指令实现地址,直接跳转执行,充分利用CPU流水线机制提升性能。这种设计避免了传统的s原创 2026-04-04 12:30:46 · 361 阅读 · 0 评论 -
解释器函数栈原理(三)退出
本文详细解析了Java虚拟机中函数退出的机制,重点分析了ireturn字节码的执行过程。文章首先展示了函数返回的字节码示例,指出ireturn负责函数退出操作。随后深入剖析了remove_activation函数的实现细节,包括如何通过寄存器操作恢复调用栈状态:1)将栈中保存的sender_sp值存入rbx;2)通过leave指令还原rbp和rsp;3)将返回地址存入rbcp寄存器。最后解释了jmp指令如何跳转回调用者继续执行。整个过程完整展现了Java函数调用栈的退出机制,对理解虚拟机工作原理具有重要意义原创 2026-04-01 13:15:08 · 223 阅读 · 0 评论 -
解释器函数栈原理(二)使用
本文通过Java字节码示例详细讲解了解释器函数栈的工作原理。文章首先说明函数栈的高地址用于存储本地变量表(包含参数和成员变量),低地址用于操作数栈。以sum(i,j)方法为例,分析了其字节码执行过程:iload指令通过取负索引访问本地变量表,将变量值压入操作数栈;iadd指令完成栈顶两个元素的相加操作。最后指出本地变量表位于栈高地址端,操作数栈在低地址端,访问本地变量时需要将索引取负值进行偏移计算。整个过程清晰展示了函数栈的内存布局和字节码执行机制。原创 2026-03-31 17:13:40 · 211 阅读 · 0 评论 -
解释器函数栈原理(一) 建栈
本文主要介绍了HotSpot虚拟机中解释器函数栈的构建原理,重点分析了generate_normal_entry函数的实现细节。文章首先说明了如何使用宏汇编定义各参数在内存中的位置,并解释了偏移量的确定方法。随后详细讲解了参数保存和局部变量处理的逻辑,包括参数个数的计算、本地变量表的初始化过程。最后阐述了Java函数栈的构建过程,包括返回地址和栈基地址的压栈操作,以及如何定位call_stub的栈顶位置。文章通过内存布局图和代码片段相结合的方式,清晰地展示了函数栈构建的关键步骤和实现原理。原创 2026-03-30 12:39:42 · 389 阅读 · 0 评论 -
解释器入口地址的生成
解释器入口地址生成 通过分析HotSpot源码,可以得出以下结论: 解释器入口地址是通过AbstractInterpreterGenerator::generate_method_entry()函数生成的,该函数会根据方法类型创建对应的入口点。 对于普通Java方法,入口地址存储在Method::_i2i_entry字段中,这个字段在方法链接阶段被设置。 入口地址的生成过程涉及: 创建解释器代码段 生成特定方法的入口汇编代码 将入口地址与Java方法关联 关键代码路径: // 生成方法入口 address原创 2026-03-28 10:38:35 · 261 阅读 · 0 评论 -
hotspot如何从C++逻辑跳入JVM逻辑
本文分析了HotSpot JVM中call_stub的实现机制,重点解读了x86平台下生成汇编指令的过程。文章首先指出call_stub的实现在stubGenerator_x86_64.cpp文件中,通过StubCodeMark和碰撞指针方式分配内存。然后详细解释了如何通过C++代码生成汇编指令,包括Address类表示内存地址、寄存器操作等关键点。文章通过图示展示了参数在栈中的布局,并解析了宏汇编指令与真实汇编的对应关系。最后说明了如何保存调用函数的寄存器状态,为后续跳转JVM逻辑做准备。原创 2026-01-24 21:07:23 · 176 阅读 · 0 评论 -
hotspot桩代码
摘要:桩代码是程序执行在不同例程间跳转时所需的过渡代码,用于处理运行环境转换和参数传递。HotSpot虚拟机中,桩代码通过定义入口地址实现跳转功能,平台相关的桩代码生成由汇编指令实现。以C++转入JVM为例,通过JavaCalls::call_helper调用桩代码完成环境切换,其中call_stub函数指针指向生成的汇编指令首地址,实现执行流程的平滑过渡。原创 2026-01-23 21:28:19 · 364 阅读 · 0 评论 -
hotspot中函数类
文章摘要: 本文详细分析了Java函数在HotSpot虚拟机中的实现机制。首先介绍了Java字节码中函数描述的结构,包括访问标志、名称索引和描述符索引等。通过示例代码展示了Java函数编译后的字节码表示形式。重点解析了HotSpot中Method类的设计,说明其如何继承Metadata类并封装函数的关键属性如访问权限、函数名和参数表。文章还提供了使用gdb调试Java类加载过程的方法,帮助读者深入理解函数在虚拟机内部的解析和存储机制。最后通过调试会话展示了具体函数解析时的内存状态。原创 2026-01-22 23:05:01 · 37 阅读 · 0 评论 -
hotspot中的Java类对象如何保存虚函数
本文分析了HotSpot虚拟机中Java类对象的虚函数保存机制。Java中可被继承的非静态、非私有、非final方法被视为虚函数,通过invokevirtual字节码调用。HotSpot使用Klass类的vtable字段存储虚函数,其中包含虚函数表长度和方法指针。通过调试Object类发现,其5个方法(hashCode、equals、clone、toString、finalize)属于虚函数,而final修饰的方法则不是。虚函数表内存布局从Klass对象起始地址偏移固定位置开始,按顺序存放各虚函数的方法指针原创 2026-01-18 14:24:49 · 185 阅读 · 0 评论 -
hotspot中的Java类对象如何保存注解
摘要:HotSpot虚拟机通过Annotations类保存Java类对象的注解信息,包括类注解(_class_annotations)、字段注解(_fields_annotations)及其类型注解(_class_type_annotations/_fields_type_annotations)。注解在字节码解析阶段被提取,其中类注解作用于类声明,类型注解作用于泛型等类型声明。InstanceKlass类通过_annotations字段维护所有注解信息,支持运行时通过反射获取。这种机制实现了JDK5.0引原创 2026-01-18 10:10:13 · 100 阅读 · 0 评论 -
类加载器分析(五)启动类加载器 之 关于如何取出字段泛型数据类型定义
摘要:本文分析了HotSpot虚拟机中字段泛型签名的存储结构。当类字段包含泛型类型时,泛型签名索引(generic_signature_index)会被集中存储在字段数组末尾。通过FieldStreamBase类的算法,首先计算_generic_signature_slot起始位置,再通过遍历字段判断泛型标志位,最终定位到具体的泛型签名索引。当访问下一个泛型字段时,只需将_generic_signature_slot递增1即可。该设计有效解决了泛型签名索引与字段的对应关系问题,保证了泛型信息的准确获取。原创 2026-01-17 17:53:32 · 36 阅读 · 0 评论 -
类加载器分析(四)启动类加载器 之 字段
本文分析了Java类加载过程中字段信息的处理机制。通过String类的示例展示了字段的获取方式,包括字段名称、类型、修饰符等信息。重点探讨了HotSpot虚拟机中InstanceKlass类的_fields和_java_fields_count成员变量如何存储字段信息,并追踪了字段获取的时机——在字节码解析阶段完成。具体实现上,ClassFileParser类在解析字节码后会将其_fields和_java_fields_count赋值给InstanceKlass类,从而完成字段信息的加载。文章结合代码示例和原创 2026-01-16 13:56:03 · 84 阅读 · 0 评论 -
启动类加载器(一)名称,接口,父类
摘要:本文分析了Java虚拟机中的启动类加载器(Bootstrap Class Loader)的工作原理。启动类加载器使用C++实现,负责加载JVM基础类如Object和String。通过调试分析发现,Klass类描述Java类元信息,InstanceKlass继承Klass并包含具体类信息。文中展示了gdb调试过程,验证了String类加载时正确识别其实现的5个接口(Serializable、Comparable等)。调试结果表明启动类加载器能准确加载基础类及其接口信息。原创 2026-01-15 12:14:52 · 79 阅读 · 0 评论 -
类加载器分析(二)类加载器中的Module
本文介绍了Java 9引入的模块系统(Module)及其与类加载器的关系。模块是Java 9的新特性,通过module-info.java文件定义模块依赖和访问控制。在类加载过程中,加载器会优先判断类是否属于某个模块,若属于则调用对应模块的加载器。Module类包含模块名称、类加载器引用和模块描述器(ModuleDescriptor),后者记录模块的依赖、导出包等信息。文章还通过类图展示了模块描述器的结构,并说明了类加载时模块的优先级判断流程。原创 2026-01-11 15:45:19 · 44 阅读 · 0 评论 -
类加载器分析(一) 应用类加载器
本文介绍了Java类加载机制及其实现原理。类加载是将.class文件加载到内存并转换为可执行类型的过程,包括加载、连接和初始化三个阶段。Java采用双亲委派模型实现类加载,子加载器会先委托父加载器尝试加载类,只有父加载器无法完成时才自行加载。文章通过分析类加载器继承关系和调试实例,展示了AppClassLoader的工作流程,以及如何通过系统类加载器获取Class对象。这种机制在运行时完成类加载,为Java提供了高度灵活性和扩展性。原创 2026-01-08 13:53:14 · 203 阅读 · 0 评论 -
常量池源码分析
本文摘要: Java虚拟机通过常量池实现动态连接,将类型等信息保存在内存中以便动态加载。常量池位于.class文件的第8字节开始,其中第9-10字节表示元素个数。常量池索引从1开始,容量为n-1。通过分析字节码文件可知,常量池项目以表结构存储,包含tag标识类型和index指向其他项目。OpenJDK源码使用枚举和类结构描述常量池项目类型,如Methodref、Fieldref等。ConstantPool类继承Metadata,包含tags数组记录类型、版本号等属性,并与类对象关联。通过解析字节码文件,可将原创 2026-01-03 23:53:42 · 22 阅读 · 0 评论 -
函数中碰撞指针的应用
本文分析了HotSpot中函数内部变量使用碰撞指针内存区域的技术实现。以ClassLoader::load_class函数为例,展示了ResourceMark类如何管理内存分配:通过构造函数保存当前线程的ResourceArea状态,析构函数还原状态,实现快速内存回收。文中详细解析了ResourceMark和ResourceObj的内存管理机制,包括保存和恢复内存指针状态的过程,以及ClassFileStream类如何通过继承ResourceObj来利用碰撞指针优化内存分配。原创 2025-12-30 10:05:24 · 38 阅读 · 0 评论 -
碰撞指针(Bump-in pointer)
碰撞指针内存分配机制 碰撞指针(Bump-in pointer)是一种高效的内存分配方法,其核心原理是在预分配的大块内存区域(Chunk)中通过移动高水位线(_hwm)指针来分配对象空间。与传统的malloc/free相比,这种方法避免了频繁的系统调用和内存碎片问题。 关键实现包括: 使用Chunk类管理内存块,通过链表连接多个Chunk Arena类负责分配管理,通过_hwm和_max指针标记已用/可用空间边界 当空间不足时自动扩展新的Chunk ResourceObj类重载new运算符,确保对象在Are原创 2025-12-28 14:02:13 · 688 阅读 · 0 评论 -
JVM中对于源码中符号的管理
本文探讨了JVM中符号管理的实现机制。首先通过C语言示例说明符号的基本概念和用途,分析了静态语言编译器(gcc)如何处理符号并存储在目标文件的符号表中。然后重点阐述了JVM中的符号管理,指出Java符号在运行时动态生成并存储在元数据区。详细解析了Symbol类的三个关键成员变量:_hash_and_refcount(包含哈希值和引用计数)、_length(符号长度)和_body(符号内容)。文章通过对比静态语言和JVM的符号处理方式,揭示了JVM符号管理的独特设计。原创 2025-12-26 10:41:31 · 911 阅读 · 0 评论 -
JVM的内存管理
摘要: JVM内存管理涉及堆、栈和元数据区域的管理。堆内存通过CHeapObj类使用malloc分配,栈对象随函数栈自动释放。元数据区域(MetaspaceObj)存储Java类信息,采用高效块分配算法管理。JVM通过自定义内存管理类(如SpaceManager和Metachunk)实现精细化内存控制,将管理对象与被管理内存分离。CodeHeap等特殊区域采用独特分配策略,体现了JVM内存管理的复杂性和高效性。 (149字)原创 2025-12-11 16:26:02 · 543 阅读 · 0 评论 -
关于JVM中重定位的问题
文章摘要: 本文探讨了JVM中的重定位问题,将其分为两类:整片代码重定位(代码块移动或替换时更新内存地址)和单个指令重定位(运行时动态确定指令操作数地址)。通过C语言编译示例展示了重定位的基本原理,并分析了HotSpot中的实现机制,包括relocInfo类记录重定位信息、RelocationHolder管理重定位对象,以及AddressLiteral处理字面地址重定位。文章结合代码片段和架构图,详细说明了重定位值的计算方法和实际应用场景。原创 2025-12-03 15:21:07 · 804 阅读 · 0 评论 -
JVM堆的管理者——CodeCache
JVM中的CodeCache是用于存储JIT编译生成的本地代码的内存区域。本文分析了CodeCache的关键实现细节原创 2025-11-06 15:30:16 · 329 阅读 · 0 评论 -
CodeBuffer与CodeBlob
本文分析了HotSpot虚拟机中的CodeBuffer和CodeBlob组件。CodeBuffer作为指令生成的临时缓冲区,包含consts、insts和stubs三个CodeSection。生成后的指令会先存放在CodeBuffer中,经过优化后才会存入永久内存CodeBlob。CodeBlob是二进制对象的管理者,根据编译等级(Level 0-4)分为MethodNonProfiled、MethodProfiled等不同类别。文章详细介绍了CodeBlob的内存布局,包含_code_begin、_cod原创 2025-11-05 16:19:38 · 650 阅读 · 0 评论 -
openjdk底层(hotspot)汇编指令的内存分布
本文介绍了内存分段机制及其在JVM中的实现。通过CodeSection类模拟内存中的段结构,详细说明了其关键属性如_start、_end、_limit等的作用。在JVM中,CodeBuffer类用于管理不同类型的CodeSection(常量段、指令段、桩代码段),并展示了指令插入指令段(_insts)的具体过程。文章还通过gdb调试示例,演示了如何在实际运行中查看CodeSection的内存布局,说明其起始地址对齐和段长度设计对CPU访存性能的优化。原创 2025-05-25 23:04:03 · 961 阅读 · 0 评论 -
openjdk底层(hotspot)汇编指令调用(五)——内存访问
在aarch64架构下,src\hotspot\cpu\架构文件夹中的文件如assembler_xx.hpp和register_xx.hpp等,主要涉及寄存器定义和汇编编码函数的实现。文章进一步探讨了计算机中寄存器和内存之间的数据访问方式,特别是在x86架构下的访存模型。通过具体示例,如movl %rdi, (%rbp),展示了如何将寄存器中的数据存储到内存中,或从内存加载数据到寄存器。此外,文章还介绍了x86架构中的基地址、变址和比例因子等概念,并说明了如何在hotspot的x86访存模型中通过Addre原创 2025-05-20 11:01:00 · 635 阅读 · 0 评论 -
openjdk底层(hotspot)汇编指令调用(四)——发送指令到内存
文章主要讨论了JVM如何将指令发送到代码段中执行。首先,JVM通过软件模拟计算机行为,将内存分为数据段和代码段。在指令编码完成后,JVM通过assembler_aarch64.hpp文件中的add函数将指令发送到代码段。原创 2025-05-15 11:43:33 · 571 阅读 · 0 评论 -
openjdk底层(hotspot)汇编指令调用(三)——编码
本文以AArch64架构的add x0,x1,x2指令为例,详细介绍了如何实现指令编码。原创 2025-05-13 16:55:22 · 556 阅读 · 0 评论 -
openjdk底层(hotspot)汇编指令调用(二)——寄存器定义
通过面向对象编程思想,定义了寄存器类和汇编器类,分别用于管理寄存器的名称、值以及汇编指令的编码规则。为了支持多平台,OpenJDK在share/asm目录下抽象了寄存器和汇编器的基类。原创 2025-05-12 10:13:37 · 1151 阅读 · 0 评论 -
openjdk底层(hotspot)汇编指令调用(一)——汇编指令及指令编码基础
计算机通过识别0和1的电信号执行指令,早期程序员直接使用二进制编程,但易出错且不便记忆。为此,厂商定义了汇编指令,如x64平台的push %rbx对应二进制0x53。原创 2025-05-11 20:58:23 · 1414 阅读 · 0 评论 -
JVM局部变量表和操作数栈的内存布局
局部变量表(locals)包括了函数内部的临时变量和形参,另外还包括了当前函数的this指针操作数栈实现了Java虚拟机的栈式操作在openjdk的实现中,局部变量表位于解释栈的高地址处,用locals寄存器定位局部变量表并根据偏移值获取值;操作数栈位于解释栈的低地址,用sp寄存器定位实现字节码逻辑。原创 2025-05-07 11:19:12 · 614 阅读 · 0 评论 -
字节,字节码,字节码文件,字节码指令
计算机一般是一个字节一个字节的读取数据,使用字节进行编码符合计算机的读取数据的流程。第三,使用通用的字节码指令针对的是纯软件的虚拟机,其内容与平台无关。因此使用字节码的程序很方便移植,甚至可以说不需要任何操作,直接放在有Java虚拟机的机器上运行即可,实现了。这些字节根据Java虚拟机规范的要求在不同的位置表达不同的意思。由于电路实现上的原因,计算机的计数方式为二进制,即由0和1组成。为了方便的表示字节,一般采用16进制的形式。生成的.class文件为01组成的文件,使用vs code的。原创 2025-04-24 09:43:37 · 1204 阅读 · 0 评论 -
配置openjdk调试环境
如何调试openjdk原创 2025-04-22 21:02:45 · 927 阅读 · 0 评论 -
关于编译和调试OpenJDK的一些问题
由于`OpenJDK`的编译环境是跟操作系统紧密相关的,所以,当分析`OpenJDK`代码的时候,首先应该阅读`README.md`,确定当前阅读的`OpenJDK`能够在哪些环境下进行编译和调试。这里将一些基本需要解决的问题进行阐述。原创 2025-04-21 14:25:11 · 667 阅读 · 0 评论 -
在Ubuntu 18.04下编译OpenJDK 11
链接: https://pan.baidu.com/s/1QAdu-B6n9KqeBakGlpBS3Q 密码: 8lho不同版本的jdk会要求在不同版本的Ubuntu下编译,不要用太高版本的Ubuntu或者gcc,特别是gcc,这个跟glibc的版本还绑定,如果gcc版本太高,则glibc版本也高,也会影响openjdk的编译。gcc7,freetype2可以直接使用apt-get install安装先configure,再makeconfigure可以参考openjdk/doc/building.htm原创 2025-04-21 13:50:36 · 696 阅读 · 0 评论 -
Java虚拟机(JVM)平台无关?相关?
平台无关是因为其执行过程是由纯软件实现的栈式计算机实现,而平台相关是因为Java虚拟机的具体操作跟平台指令和操作系统相关。不仅如此,为了能够实现**“一次编译,处处执行”**,Java虚拟机还能根据不同的操作系统进行适配,对于有些与操作系统和CPU结合的部分,也提供了不同的实现。所以,如果有程序要实现一个加法,那么在计算机底层执行时,其执行的内容是不一样的。上生成的.class文件,其内容是一样的。Tape是输入数据,Program是针对这些数据进行计算的程序,中间横着的方块表示的是机器的状态。原创 2025-04-17 17:25:21 · 1001 阅读 · 0 评论 -
openjdk11 compiling failure undefined JvmtiSampledObjectAllocEventCollector::object_alloc_is_safe_to
【代码】openjdk11 compiling failure undefined JvmtiSampledObjectAllocEventCollector::object_alloc_is_safe_to。原创 2023-05-26 14:34:31 · 241 阅读 · 0 评论 -
Hadoop学习中VMWare的网路配置
Hadoop学习中VMWare的网路配置1 背景为了学习Hadoop,则在自己的机器上模拟构建一个集群环境2 VMWare网络配置步骤首先在VMWare中新建一个网络适配器在VMWare中“编辑”–>“虚拟网络编辑器”–>“添加网络”设置网络设置NAT在Windows的网络连接中设置右键设置IPV4这里表示是Windows的IP,也就是Windows自己有了2个IP,一个是路由器DHCP分配的,一个是自己设置的网络连接的结构是这样的3 VMWare中的Cen原创 2022-03-28 15:59:31 · 2570 阅读 · 0 评论
分享