Klass与Oop
前段时间,一直在看《Hotspot实战》,顺便编译了一份OpenJDK的源码,然后就在eclipse里面调试起来。
虽然我的入门语言是c/c++,但是被Java拉过来好几年了,现在再看源码,熟悉又陌生,好在慢慢找到了感觉。
这是分析Hotspot源码的第一篇,讲一下Klass和Oop这两种数据结构。
系统的介绍和讲解,可以查看https://yq.aliyun.com/articles/20279和http://www.jianshu.com/p/252e27863822这两篇文章。确实写的比较好,深入而且透彻。另外可以再看看《Hotspot实战》的第3章。
我这里主要看看Klass和Oop的内存布局。

当时看这张图的时候,有一个巨大的疑问,instanceKlass的数据结构与图不符,没有对象头(Mark和Klass这两个属性)。
真是百思不得其解。
于是,继续看源码。
1)对象头里的Klass这个属性,是一个klassOopDesc类型的指针,并不是一个指向Klass类的指针。why???
看了之前的第一篇文章,豁然开朗。在JDK8之前,方法区内的描述类型的元数据对象,也是由GC管理的。所有由GC统一管理的对象,都要继承自oopDesc,所以才会诞生klassOopDesc这个类型。从JDK8开始,类型元数据都移出了GC堆,所以Klass这个属性可以直接指向Klass类了。
2)klassOopDesc只有从父类继承过来的Mark和Klass这两个属性,并没有指向Klass类的指针,那oop是如何找到对应的Klass的呢???
klassOopDesc内部有一个方法:klass_part()
// returns the Klass part containing dispatching behavior
Klass* klass_part() const { return (Klass*)((address)this + sizeof(klassOopDesc)); }
这个方法果然返回一个指向Klass的指针,但是计算过程比较诡异,在当前klassOopDesc对象的首地址增加sizeof(klassOopDesc)这么多空间后的地址。也就是说,一个klassOopDesc对象数据和对应的Klass对象数据,是从上到下紧密的排列着,有了klassOopDesc的指针,就能顺藤摸瓜找到对应的Klass数据。
那当初构造的时候,是按这种模式在内存分配数据的吗???
之前的第二篇文章,讲的巨细。可以看到,在类加载的过程中,构造了一个空的Klass对象,然后调用了Klass类的as_klassOop方法返回klassOopDesc的指针。
// returns the enclosing klassOop
klassOop as_klassOop() const {
// see klassOop.hpp for layout.
return (klassOop) (((char*) this) - sizeof(klassOopDesc));
}
klassOop是klassOopDesc指针的一个别名。构造的时候,首地址减去sizeof(klassOopDesc)这么多空间后的地址。这时候,内存空间是分配出来了,具体的数据,在后续过程中填充。
最后说下看源码心得体会 :其实那张图上的数据排列结构是对的,但是具体的实现方式,如果不看源码肯定会很疑惑。另外,看到这么犀利的指针操作,对c/c++的好感真是倍增。
Klass与Oop的更多相关文章
- 深入解析Java反射-invoke方法
博客原文:http://www.sczyh30.com/posts/Java/java-reflection-2/ 上篇文章中回顾了一下Java反射相关的基础内容.这一节我们来深入研究Method类中 ...
- 深入理解java虚拟机---对象的结构(九)
注意: 我们可以看到的就是InstanceData的数据. 先转载一篇文章作为开头,因为讲的非常详细,我就简单加工下放到这里: 对象结构 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区 ...
- 深入理解多线程(二)—— Java的对象模型
上一篇文章中简单介绍过synchronized关键字的方式,其中,同步代码块使用monitorenter和monitorexit两个指令实现,同步方法使用ACC_SYNCHRONIZED标记符实现.后 ...
- Java对象结构及HotSpot对象模型
一.对象结构 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header).实例数据(Instance Data)和对齐填充(Padding).下图是普通对象实例与数组对象 ...
- 从Oop-Klass模型看透反射
<红楼梦>第十二回,贾瑞因痴迷王熙凤,被王熙凤折腾的眼看就快不行了.当然这里面是没有多少爱的,完全因王熙凤的美貌而起.就在这时来了一个跛足道人,带来了一面宝镜,说能治好贾瑞的病.当然这可不 ...
- HotSpot二分模型(1)
HotSpot采用了OOP-Klass模型来描述Java类和对象.OOP(Ordinary Object Pointer)指的是普通对象指针,而Klass用来描述对象的具体类型. 那么为何要设计这样一 ...
- HotSpot源码分析之C++对象的内存布局
HotSpot采用了OOP-Klass模型来描述Java类和对象.OOP(Ordinary Object Pointer)指的是普通对象指针,而Klass用来描述对象的具体类型.为了更好理解这个模型, ...
- 深入理解Java中的反射机制和使用原理!详细解析invoke方法的执行和使用
反射的概念 反射: Refelection,反射是Java的特征之一,允许运行中的Java程序获取自身信息,并可以操作类或者对象的内部属性 通过反射,可以在运行时获得程序或者程序中的每一个类型的成员活 ...
- jvm源码解读--17 Java的wait()、notify()学习
write and debug by 张艳涛 wait()和notify()的通常用法 A线程取得锁,执行wait(),释放锁; B线程取得锁,完成业务后执行notify(),再释放锁; B线程释放锁 ...
随机推荐
- String、StringBuffer、StringBuilder比较
String.StringBuffer.StringBuilder三者是字符串中重要的内容,也是面试过程中经常问到的问题,下面就来总结一下三者的区别. 1.三者都可以存储和操作字符串. 2.Strin ...
- python基础操作_方法(函数)
#函数,方法#普通方法def hello(): print('hello')hello()#带形参的方法def hello1(name): print('hello%s'%name)hello1('布 ...
- PhpStorm 设置之主题
一 打开设置 File --> settings 二 设置窗口字体.大小.主题 Appearance & Behavior --> Appearance 下面是本人自己比较偏爱的一 ...
- [Lucene]-Lucene基本概述以及简单实例
一.Lucene基本介绍: 基本信息:Lucene 是 Apache 软件基金会的一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎.Luc ...
- 利用document的readyState去实现页面加载中的效果
打开新的网页时,为了增强友好性体验,告知用户网页正在加载数据需要呈现一个"页面加载中"之类的提示,只需要利用document就可以实现. 实现示例代码如下: <style&g ...
- python面向对象的编程
self相当于在实例化类的过程中传入参数,实例化对象本身 静态方法,静态字段属于类,动态字段,动态方法输入每一个实例化的对象 类实例化的过程把一些属性,方法封装到一个实例化对象当中 动态字段,动态方法 ...
- 如何将mysql数据导入Hadoop之Sqoop安装
Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysql.postgresql...)间进行数据的传递,可以将一个关系型数据库(例如 : MySQL ,Oracle , ...
- nginx二级域名配置自动跳转到一级域名
nginx二级域名配置自动跳转到一级域名 rewrite配置内容: if ($http_host !~ "^www.aaa.com$") { rewrite ^(.*) http: ...
- Linux系统vi模式下显示行号
在命令模式下输入:set nu或者:set number都可以为vi设置行号,如果要取消的话,则输入:set nonu行号的设置是vi的环境设置,不会影响文本的内容.
- Swift初始化空字符串
为了构造一个很长的字符串,可以创建一个空字符串作为初始值.可以将空的字符串字面量赋值给变量,也可以初始化一个新的String 实例: var emptyString = "" // ...