- 博客(315)
- 资源 (13)
- 问答 (1)
- 收藏
- 关注
原创 模板解释器
模板解释器概述 模板解释器是JVM中用于提升字节码执行效率的一种技术。它通过预先为每个字节码指令定义汇编实现模板,并将这些模板存储在模板表中。每个模板包含标志位、输入/输出栈顶状态、生成函数指针等属性。在初始化阶段,模板表会为所有字节码指令注册对应的模板实现。执行时,解释器直接调用相应字节码的预生成汇编代码,避免了switch-case带来的性能损耗。这种设计显著提高了字节码解释执行的效率,是JVM解释器实现的关键优化手段。
2026-04-09 15:08:47
194
原创 解释器指令入口——栈顶缓存
本文深入探讨了Java虚拟机中解释器指令执行的栈顶缓存机制。通过两个具体示例分析了栈顶状态对字节码执行的影响:当栈顶状态一致时直接更新寄存器,不一致时需进行压栈操作。文章详细介绍了HotSpot虚拟机如何通过模板表(TemplateTable)定义每个字节码的输入输出栈顶状态,并生成相应的汇编代码。栈顶缓存的本质是根据下一条指令的需求决定上一条指令结果存放位置(寄存器或内存),这种机制有效优化了解释器的执行效率。文章还通过NOP指令的极端案例展示了栈顶状态转换的实际应用。
2026-04-06 18:00:59
375
原创 解释器指令入口——转发表
HotSpot JVM采用转发表机制高效执行字节码指令,避免分支判断导致的流水线冲刷。转发表是一个二维表,行表示栈顶状态(如int、long等),列表示256个字节码指令。每个单元格存储对应指令的汇编实现入口地址。JVM初始化时通过set_entry_points_for_all_bytes()填充转发表,将各字节码指令的实现地址按栈顶状态分类存储。执行时,JVM通过dispatch_next从转发表快速查找当前栈顶状态下的指令实现地址,直接跳转执行,充分利用CPU流水线机制提升性能。这种设计避免了传统的s
2026-04-04 12:30:46
338
原创 解释器函数栈原理(三)退出
本文详细解析了Java虚拟机中函数退出的机制,重点分析了ireturn字节码的执行过程。文章首先展示了函数返回的字节码示例,指出ireturn负责函数退出操作。随后深入剖析了remove_activation函数的实现细节,包括如何通过寄存器操作恢复调用栈状态:1)将栈中保存的sender_sp值存入rbx;2)通过leave指令还原rbp和rsp;3)将返回地址存入rbcp寄存器。最后解释了jmp指令如何跳转回调用者继续执行。整个过程完整展现了Java函数调用栈的退出机制,对理解虚拟机工作原理具有重要意义
2026-04-01 13:15:08
206
原创 解释器函数栈原理(二)使用
本文通过Java字节码示例详细讲解了解释器函数栈的工作原理。文章首先说明函数栈的高地址用于存储本地变量表(包含参数和成员变量),低地址用于操作数栈。以sum(i,j)方法为例,分析了其字节码执行过程:iload指令通过取负索引访问本地变量表,将变量值压入操作数栈;iadd指令完成栈顶两个元素的相加操作。最后指出本地变量表位于栈高地址端,操作数栈在低地址端,访问本地变量时需要将索引取负值进行偏移计算。整个过程清晰展示了函数栈的内存布局和字节码执行机制。
2026-03-31 17:13:40
191
原创 解释器函数栈原理(一) 建栈
本文主要介绍了HotSpot虚拟机中解释器函数栈的构建原理,重点分析了generate_normal_entry函数的实现细节。文章首先说明了如何使用宏汇编定义各参数在内存中的位置,并解释了偏移量的确定方法。随后详细讲解了参数保存和局部变量处理的逻辑,包括参数个数的计算、本地变量表的初始化过程。最后阐述了Java函数栈的构建过程,包括返回地址和栈基地址的压栈操作,以及如何定位call_stub的栈顶位置。文章通过内存布局图和代码片段相结合的方式,清晰地展示了函数栈构建的关键步骤和实现原理。
2026-03-30 12:39:42
374
原创 解释器入口地址的生成
解释器入口地址生成 通过分析HotSpot源码,可以得出以下结论: 解释器入口地址是通过AbstractInterpreterGenerator::generate_method_entry()函数生成的,该函数会根据方法类型创建对应的入口点。 对于普通Java方法,入口地址存储在Method::_i2i_entry字段中,这个字段在方法链接阶段被设置。 入口地址的生成过程涉及: 创建解释器代码段 生成特定方法的入口汇编代码 将入口地址与Java方法关联 关键代码路径: // 生成方法入口 address
2026-03-28 10:38:35
239
原创 hotspot如何从C++逻辑跳入JVM逻辑
本文分析了HotSpot JVM中call_stub的实现机制,重点解读了x86平台下生成汇编指令的过程。文章首先指出call_stub的实现在stubGenerator_x86_64.cpp文件中,通过StubCodeMark和碰撞指针方式分配内存。然后详细解释了如何通过C++代码生成汇编指令,包括Address类表示内存地址、寄存器操作等关键点。文章通过图示展示了参数在栈中的布局,并解析了宏汇编指令与真实汇编的对应关系。最后说明了如何保存调用函数的寄存器状态,为后续跳转JVM逻辑做准备。
2026-01-24 21:07:23
147
原创 hotspot桩代码
摘要:桩代码是程序执行在不同例程间跳转时所需的过渡代码,用于处理运行环境转换和参数传递。HotSpot虚拟机中,桩代码通过定义入口地址实现跳转功能,平台相关的桩代码生成由汇编指令实现。以C++转入JVM为例,通过JavaCalls::call_helper调用桩代码完成环境切换,其中call_stub函数指针指向生成的汇编指令首地址,实现执行流程的平滑过渡。
2026-01-23 21:28:19
354
原创 hotspot中函数类
文章摘要: 本文详细分析了Java函数在HotSpot虚拟机中的实现机制。首先介绍了Java字节码中函数描述的结构,包括访问标志、名称索引和描述符索引等。通过示例代码展示了Java函数编译后的字节码表示形式。重点解析了HotSpot中Method类的设计,说明其如何继承Metadata类并封装函数的关键属性如访问权限、函数名和参数表。文章还提供了使用gdb调试Java类加载过程的方法,帮助读者深入理解函数在虚拟机内部的解析和存储机制。最后通过调试会话展示了具体函数解析时的内存状态。
2026-01-22 23:05:01
12
原创 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
173
原创 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
88
原创 类加载器分析(五)启动类加载器 之 关于如何取出字段泛型数据类型定义
摘要:本文分析了HotSpot虚拟机中字段泛型签名的存储结构。当类字段包含泛型类型时,泛型签名索引(generic_signature_index)会被集中存储在字段数组末尾。通过FieldStreamBase类的算法,首先计算_generic_signature_slot起始位置,再通过遍历字段判断泛型标志位,最终定位到具体的泛型签名索引。当访问下一个泛型字段时,只需将_generic_signature_slot递增1即可。该设计有效解决了泛型签名索引与字段的对应关系问题,保证了泛型信息的准确获取。
2026-01-17 17:53:32
29
原创 类加载器分析(四)启动类加载器 之 字段
本文分析了Java类加载过程中字段信息的处理机制。通过String类的示例展示了字段的获取方式,包括字段名称、类型、修饰符等信息。重点探讨了HotSpot虚拟机中InstanceKlass类的_fields和_java_fields_count成员变量如何存储字段信息,并追踪了字段获取的时机——在字节码解析阶段完成。具体实现上,ClassFileParser类在解析字节码后会将其_fields和_java_fields_count赋值给InstanceKlass类,从而完成字段信息的加载。文章结合代码示例和
2026-01-16 13:56:03
68
原创 启动类加载器(一)名称,接口,父类
摘要:本文分析了Java虚拟机中的启动类加载器(Bootstrap Class Loader)的工作原理。启动类加载器使用C++实现,负责加载JVM基础类如Object和String。通过调试分析发现,Klass类描述Java类元信息,InstanceKlass继承Klass并包含具体类信息。文中展示了gdb调试过程,验证了String类加载时正确识别其实现的5个接口(Serializable、Comparable等)。调试结果表明启动类加载器能准确加载基础类及其接口信息。
2026-01-15 12:14:52
67
原创 类加载器分析(二)类加载器中的Module
本文介绍了Java 9引入的模块系统(Module)及其与类加载器的关系。模块是Java 9的新特性,通过module-info.java文件定义模块依赖和访问控制。在类加载过程中,加载器会优先判断类是否属于某个模块,若属于则调用对应模块的加载器。Module类包含模块名称、类加载器引用和模块描述器(ModuleDescriptor),后者记录模块的依赖、导出包等信息。文章还通过类图展示了模块描述器的结构,并说明了类加载时模块的优先级判断流程。
2026-01-11 15:45:19
34
翻译 Java模块化之旅
Java 9模块化系统(JPMS)是Java平台的重要革新,它通过模块描述文件(module-info.java)实现了代码的强封装和更好的组织管理。本文全面介绍了模块的概念、结构(包含包、资源和描述文件)以及四种模块类型。重点解析了10种模块指令的用法,包括依赖声明(requires)、API导出(exports)、服务提供(provides...with)和反射控制(opens)等。同时介绍了默认模块分类和命令行操作,帮助开发者理解如何将现有项目迁移到模块化架构。通过模块化,Java应用可以获得更好的封
2026-01-10 19:49:35
81
原创 类加载器分析(一) 应用类加载器
本文介绍了Java类加载机制及其实现原理。类加载是将.class文件加载到内存并转换为可执行类型的过程,包括加载、连接和初始化三个阶段。Java采用双亲委派模型实现类加载,子加载器会先委托父加载器尝试加载类,只有父加载器无法完成时才自行加载。文章通过分析类加载器继承关系和调试实例,展示了AppClassLoader的工作流程,以及如何通过系统类加载器获取Class对象。这种机制在运行时完成类加载,为Java提供了高度灵活性和扩展性。
2026-01-08 13:53:14
178
原创 在Windows11下编译openjdk 21
本文介绍了在Windows 11系统下编译OpenJDK 21的详细步骤。主要流程包括:1)下载OpenJDK 20作为boot JDK;2)安装Cygwin并配置必要工具包;3)安装Visual Studio 2022及C++开发组件;4)调整系统语言设置为英文;5)通过VS命令行启动Cygwin环境;6)编写并执行编译脚本,区分debug和release两种版本。文中提供了完整的配置脚本,包含路径设置、工具链指定等关键参数,并说明了编译过程中的注意事项。该方法利用Windows下的Cygwin模拟UNI
2026-01-07 19:44:42
229
原创 使用IntelliJ Idea调试openjdk中的java代码
本文介绍了在IntelliJ IDEA中调试OpenJDK Java源码的步骤:1)创建Java项目并选择OpenJDK编译的JDK;2)编写测试Dog类;3)设置VM选项(-Xint)使用解释器模式运行;4)关联OpenJDK源码路径(src.zip);5)设置条件断点进行调试。通过这种方式可以深入跟踪Java类加载等底层实现,避免JVM优化影响调试过程。关键步骤包括项目配置、源码关联和调试参数设置,为研究Java底层机制提供了有效方法。
2026-01-06 00:57:18
185
原创 常量池源码分析
本文摘要: Java虚拟机通过常量池实现动态连接,将类型等信息保存在内存中以便动态加载。常量池位于.class文件的第8字节开始,其中第9-10字节表示元素个数。常量池索引从1开始,容量为n-1。通过分析字节码文件可知,常量池项目以表结构存储,包含tag标识类型和index指向其他项目。OpenJDK源码使用枚举和类结构描述常量池项目类型,如Methodref、Fieldref等。ConstantPool类继承Metadata,包含tags数组记录类型、版本号等属性,并与类对象关联。通过解析字节码文件,可将
2026-01-03 23:53:42
9
原创 函数中碰撞指针的应用
本文分析了HotSpot中函数内部变量使用碰撞指针内存区域的技术实现。以ClassLoader::load_class函数为例,展示了ResourceMark类如何管理内存分配:通过构造函数保存当前线程的ResourceArea状态,析构函数还原状态,实现快速内存回收。文中详细解析了ResourceMark和ResourceObj的内存管理机制,包括保存和恢复内存指针状态的过程,以及ClassFileStream类如何通过继承ResourceObj来利用碰撞指针优化内存分配。
2025-12-30 10:05:24
29
原创 碰撞指针(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
678
原创 如何禁止C++类对象的禁止拷贝操作
本文介绍了在C++中禁止类对象拷贝操作的两种方法:1) 通过将拷贝构造函数声明为delete来禁止对象拷贝;2) 通过删除赋值运算符来防止对象赋值导致的指针问题。文章通过具体代码示例展示了如何实现这两种禁止操作,并详细分析了如果不禁止赋值操作可能引发的内存泄漏问题。最后给出了正确的实现方式,确保类对象不会被错误拷贝或赋值,从而避免潜在的内存管理问题。
2025-12-26 14:11:52
399
原创 JVM中对于源码中符号的管理
本文探讨了JVM中符号管理的实现机制。首先通过C语言示例说明符号的基本概念和用途,分析了静态语言编译器(gcc)如何处理符号并存储在目标文件的符号表中。然后重点阐述了JVM中的符号管理,指出Java符号在运行时动态生成并存储在元数据区。详细解析了Symbol类的三个关键成员变量:_hash_and_refcount(包含哈希值和引用计数)、_length(符号长度)和_body(符号内容)。文章通过对比静态语言和JVM的符号处理方式,揭示了JVM符号管理的独特设计。
2025-12-26 10:41:31
889
原创 关于C++中的typedef typename的含义
本文解释了C++中typedef typename的用法,主要用于模板编程中声明依赖类型。通过示例展示了如何在模板类Table中使用typedef typename CONFIG::Value VALUE来定义类型别名,并说明了当模板参数为IntConfig或SymbolTableConfig时,编译器如何解析这些类型定义。文章还提到现代C++更推荐使用using VALUE = typename CONFIG::Value的语法,并以JVM hotspot中的符号表实现为例,演示了这种技术在实践中的应用场
2025-12-23 11:26:49
172
原创 JVM的内存管理
摘要: JVM内存管理涉及堆、栈和元数据区域的管理。堆内存通过CHeapObj类使用malloc分配,栈对象随函数栈自动释放。元数据区域(MetaspaceObj)存储Java类信息,采用高效块分配算法管理。JVM通过自定义内存管理类(如SpaceManager和Metachunk)实现精细化内存控制,将管理对象与被管理内存分离。CodeHeap等特殊区域采用独特分配策略,体现了JVM内存管理的复杂性和高效性。 (149字)
2025-12-11 16:26:02
532
原创 关于JVM中重定位的问题
文章摘要: 本文探讨了JVM中的重定位问题,将其分为两类:整片代码重定位(代码块移动或替换时更新内存地址)和单个指令重定位(运行时动态确定指令操作数地址)。通过C语言编译示例展示了重定位的基本原理,并分析了HotSpot中的实现机制,包括relocInfo类记录重定位信息、RelocationHolder管理重定位对象,以及AddressLiteral处理字面地址重定位。文章结合代码片段和架构图,详细说明了重定位值的计算方法和实际应用场景。
2025-12-03 15:21:07
787
翻译 深入理解JVM工具:Dynamic Attach和Serviceability Agent
本文深入探讨了JVM诊断工具Dynamic Attach和Serviceability Agent的核心特性与差异。Dynamic Attach支持实时监控和动态加载代理,适合低开销的实时诊断;而Serviceability Agent则提供对JVM内部结构的深度访问,适用于事后分析和复杂问题排查。文章通过内存泄漏案例展示了二者如何互补使用,并总结了各自适用场景:Dynamic Attach适合运行中监控,Serviceability Agent则擅长深度分析和事后调试。这些工具共同增强了JVM的性能分析和
2025-11-21 15:11:10
82
原创 JVM堆的管理者——CodeCache
JVM中的CodeCache是用于存储JIT编译生成的本地代码的内存区域。本文分析了CodeCache的关键实现细节
2025-11-06 15:30:16
317
原创 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
632
原创 详解PCA9685的PWM编程原理
摘要:PCA9685是一款通过I2C控制产生PWM信号的芯片,支持2.3-5.5V供电。它内置12位计数器(0-4095)和25MHz晶振,利用预分频寄存器(PRE_SCALE_REG)调整输出频率。频率计算公式为pre_scale_val = (25MHz/4096freq)-1。编程流程包括:I2C连接→设置MODE1寄存器→进入休眠模式→写入预分频值→唤醒芯片。典型应用如设置50Hz伺服电机频率,通过计算得到预分频值30。该芯片最多可寻址8个I2C从设备,默认地址0x40。
2025-10-29 20:37:45
698
原创 C++虚函数表
本文介绍了使用Visual Studio和GDB调试工具分析C++类内存布局的方法。通过在VS中配置/d1 reportAllClassLayout命令,可以输出类的内存结构。文章重点分析了三种情况:无虚函数类、带虚函数类以及继承类。通过反汇编和内存监视,展示了虚函数表(__vfptr)的结构,说明虚函数调用机制。对于继承类,详细演示了基类函数被覆盖时的内存布局变化。调试结果表明,虚函数表指针位于对象首地址,其中保存了虚函数的调用地址。
2025-05-26 10:33:13
539
原创 openjdk底层(hotspot)汇编指令的内存分布
本文介绍了内存分段机制及其在JVM中的实现。通过CodeSection类模拟内存中的段结构,详细说明了其关键属性如_start、_end、_limit等的作用。在JVM中,CodeBuffer类用于管理不同类型的CodeSection(常量段、指令段、桩代码段),并展示了指令插入指令段(_insts)的具体过程。文章还通过gdb调试示例,演示了如何在实际运行中查看CodeSection的内存布局,说明其起始地址对齐和段长度设计对CPU访存性能的优化。
2025-05-25 23:04:03
940
原创 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
615
原创 C#接口的setter或getter的访问性限制
在C#中,可以通过限制setter的访问性来实现只对外提供getter,而属性的赋值只能在内部进行。例如,在LibA命名空间中定义一个接口ITranslation,其中MyDict属性的setter被标记为internal,这样外部只能读取该属性,而不能直接设置。在LibB中实现该接口时,setter只能在内部使用。通过反射动态创建对象时,可以在LibA中访问setter进行赋值。这种设计适用于需要控制属性访问权限的场景,确保属性的安全性。
2025-05-19 15:07:38
410
VS2005最简单的OpenGL例子
2010-02-12
ARM汇编语言的系统号调用例程
2020-09-27
图形学DDA画直线算法
2010-02-12
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅