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线程释放锁 ...
随机推荐
- 学习web前端怎样入门?初学者赶紧看过来!
web前端怎么样才能入门,首先我们要从什么是初级web前端工程师说起: 按照我的想法,我把前端工程师分为了入门.初级.中级.高级这四个级别, 入门级别指的是了解什么是前端(前端到底是什么其实很多人还是 ...
- js继承的常用方法
写在前面的话:这篇博客不适合对面向对象一无所知的人,如果你连_proto_.prototype...都不是很了解的话,建议还是先去了解一下JavaScript面向对象的基础知识,毕竟胖子不是一口吃成的 ...
- 什么是Web Worker?
简单点说,Web Worker就是一个运行在后台的JavaScript线程,不会影响页面的响应. 我们知道,JavaScript是单线程的脚本语言,即同一时刻只能做一件事情,否则会带来极其复杂的同步问 ...
- matplotlib.pyplot.hist
**n, bins, patches = plt.hist(datasets, bins, normed=False, facecolor=None, alpha=None)** ## 函数说明 用于 ...
- Bash函数
一.什么是Bash函数 Bash不支持goto语句,可以用function实现程序流程跳转.当前shell中一组组织在一起并被命名的命令.比脚本的效率高,一旦定义,就成为shell内存的一部分,可以随 ...
- C#中==运算符
在这篇博客中,我们将介绍如下内容: ==运算符与基元类型 ==运算符与引用类型 ==运算符与String类型 ==运算符与值类型 ==运算符与泛型 ==运算符与基元类型 我们分别用两种方式比较两个整数 ...
- 2.配置Spring+SpringMvc+Mybatis(分库or读写分离)--Intellij IDAE 2016.3.5
建立好maven多模块项目后,开始使用ssm传统的框架: 1.打开总工程下的pom.xml文件:添加如下代码: <!--全局的所有版本号定义--> <properties> & ...
- Treasure Hunt
Treasure Hunt time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- win7双系统安装openSUSE13.2解决【引导加载器安装期间出错】问题
原始日期:2015-08-17 14:16 昨晚不知道哪根筋不对,突然想装一个liunx系统,与win7形成双系统,最终选定openSUSE13.2,想想以前也安装过Ubuntu,应该差不多,所以直接 ...
- java 父类构造器
当创建任何java对象时,程序总会首先调用系统的父类非静态初始化块(隐式执行)和父类构造器(从object开始(java程序中所有类的最终父类都是java.lang.Object类,使用语句super ...