从Oop-Klass模型看透反射
《红楼梦》第十二回,贾瑞因痴迷王熙凤,被王熙凤折腾的眼看就快不行了。当然这里面是没有多少爱的,完全因王熙凤的美貌而起。就在这时来了一个跛足道人,带来了一面宝镜,说能治好贾瑞的病。当然这可不是一面普通的镜子,而是由警幻仙子做制。并且道人还告诫贾瑞,这面镜子专治邪思妄动之症,有济世保生之功。所以带他到世上,单与那些聪明俊杰,风雅王孙等看照。千万不可照正面,只照他的背面。
贾瑞先是依着跛足道人的话,照的背面。可是却看到一个骷髅立在里面,把贾瑞吓了个半死。这时贾瑞以为道士骗他,赶忙照了正面,这下看到了美貌的王熙凤,贾瑞满意极了。可是他的命却没有了。
正面的那个骷髅,正是病入膏肓的贾瑞自己,可是他却不敢相信那就是他自己现在的形象。他宁愿相信假的,也不愿相信真的。跛足道人明明叫贾瑞照背面,可是贾瑞却偏偏喜欢照正面。那是因为正面有贾瑞喜欢的东西。这时,再高明的医生也救不了他了。可想曹雪芹写到这里,虽说用的是风趣幽默的语言,从中却能看出他的无奈。
每天清晨傍晚,当我们站在镜子时前可曾想过,摘掉喜好的有色眼镜打开自己的心肺肠肝,镜中是否还是自己当初想要的样子。

以铜为镜正衣冠、以史为镜知兴替、以人为镜明得失。人类需要镜子去看清自己、看清时间、看清取舍,同样的是 类也需要。
JAVA是人造语言,其中的很多机制和抽象的出现都是源于人类社会的运作方式和道理。我们要像理解自己周围的世界一样去理解语言背后的道理,就像语言的创造者用对周边世界的理解去创造这门语言时一样。
反射是学习JAVA的过程中无法绕过的大山,反射的使用容易、但理解很难,因为反射涉及到了JVM的数据结构和类加载机制等底层机制。我们从字面意思来理解一下反射,那就是靠一面“镜子”,去看清类的内部构造。
在使用时我们发现,我们通过操作一个类的java.lang.class对象,可以在运行时窥探这个类的成员、方法、注解等,事实上反射的定义也是这样:
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
想要弄清楚反射,我们不得不提的是JVM的OOP-KLASS模型(源码在openjdk-8/openjdk/hotspot/src/share/vm/oops内)。
这里的 oop 指的是 普通对象指针 (普通对象指针),它表示对象的实例信息,看起来像个指针实际上是藏在指针里的对象。而klass 则包含元数据和方法信息 ,用来描述Java类。
那么为何要设计这样一个一分为二的对象模型呢?这是因为HotSopt JVM的设计者不想让每个对象中都包含一个vtable(虚函数表),所以就把对象模型拆成klass和oop,其中oop中不包含任何虚函数,而klass就包含虚函数表,可以进行方法调度。这个模型其实是 参照的Strongtalk VM的对象模型。
klass
一个Klass对象代表一个类的元数据。它提供:
language level class object (method dictionary etc.)
provide vm dispatch behavior for the object
所有的函数都被整合到一个C++类中。
Klass对象的继承关系: xxxKlass <:< Klass <:< Metadata <:< MetaspaceObj
可以说Klass就是类在JVM中的数据结构。
oop
oop 类型其实是 oopDesc* 。在Java程序运行的过程中,每创建一个新的对象,在JVM内部就会相应地创建一个对应类型的oop对象。各种oop类的共同基类为 oopDesc 类。JVM内部,一个Java对象在内存中的布局可以连续分成两部分: instanceOopDesc 和实例数据。 instanceOopDesc 和 arrayOopDesc 又称为对象头。instanceOopDesc 对象头包含两部分信息: Mark Word 和 元数据指针 ( Klass* ):
Mark Word :instanceOopDesc中的 _mark 成员。它用于存储对象的运行时记录信息,如哈希值、GC分代年龄(Age)、锁状态标志(偏向锁、轻量级锁、重量级锁)、线程持有的锁、偏向线程ID、偏向时间戳等。Mark Word允许压缩。
元数据指针 :instanceOopDesc中的 _metadata 成员,它是联合体,可以表示未压缩的Klass指针( _klass )和压缩的Klass指针。对应的klass指针指向一个存储类的元数据的Klass对象
可以说,instanceOopDesc就是普通对象的对象头,其中有一个指针指向了它所属的Klass,也就是类结构。
JVM在加载一个类时,会在方法区创建该类的Klass对象,并同时生成一个属于该Klass对象的java.lang.class对象放于堆中,也就是java.lang.class的instanceOopDesc。当我们访问类的元数据时,是通过java.lang.class的instanceOopDesc来访问的,java.lang.class的instanceOopDesc中包含了访问该类Klass对象的属性、方法、注解等元数据的方法。
它们的指向是这样的:类A的instanceOopDesc ----> 类A的Klass -----> 类A的java.lang.class的instanceOopDesc。
也就是说Klass代表的类的元数据是不会直接暴露给对象进行访问的,而是通过Klass的java.lang.class对象来进行间接的访问。这样做可以规范外部对Klass访问的行为,防止对元数据造成破坏。
Klass持有一个指向对应java.lang.class对象的引用,叫做_java_mirro,java.lang.class对象被设计为类的元数据的一面镜子,这也是反射机制命名的原因。
从Oop-Klass模型看透反射的更多相关文章
- (1)基于tcp协议的编程模型 (2)tcp协议和udp协议的比较 (3)基于udp协议的编程模型 (4)反射机制
1.基于tcp协议的编程模型(重中之重)1.1 编程模型服务器: (1)创建ServerSocket类型的对象,并提供端口号: (2)等待客户端的连接请求,调用accept()方法: (3)使用输入输 ...
- oop klass
https://www.infoq.com/articles/Introduction-to-HotSpot 借助HotSpot SA来一窥PermGen上的对象 找出栈上的指针/引用 虚拟机随谈(一 ...
- PBR Step by Step(四)Lambertian反射模型
光照可分为局部光照和全局光照. 局部光照:直接照射到物体表面的光照 全局光照:物体表面受周围环境影响的光照 左图中点x接收到周围环境的光线照射,来自周围表面的反射光照称为全局光照:右图中点x接收来自太 ...
- PHP API反射实例
*反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用.其用途如:自动加载插件,自动生成文档,甚至可用来扩充PHP语言.php反射api由若干类组成,可帮助我们用来 ...
- HotSpot的类模型(2)
在前一篇文章 HotSpot的二分模型中已经讲过,HotSpot采用了OOP-Klass模型描述Java的类和对象.Klass模型采用Klass类及相关子类来表示具体的Java类,可以理解这些类为Ja ...
- HotSpot二分模型(1)
HotSpot采用了OOP-Klass模型来描述Java类和对象.OOP(Ordinary Object Pointer)指的是普通对象指针,而Klass用来描述对象的具体类型. 那么为何要设计这样一 ...
- HotSpot源码分析之类模型
HotSpot采用了OOP-Klass模型描述Java的类和对象.Klass模型采用Klass类及相关子类的对象来描述具体的Java类.一般HotSpot JVM 在加载Java的Class 文件时, ...
- 【夯实PHP基础】PHP的反射机制
本文地址 分享提纲: 1. 介绍 2. 具体例子 2.1 创建Persion类 2.2 反射过程 2.3 反射后使用 1. 介绍 -- PHP5添加了一项新的功能:Reflection.这个功能使得p ...
- php反射机制
PHP5添加了一项新的功能:Reflection.这个功能使得phper可以reverse-engineer class, interface,function,method and extensio ...
随机推荐
- ASP.NET的MVC请求处理流程
1.用户打开浏览器,在地址栏输入某个网址的URL并回车,浏览器便开始像该URL指定的服务器发起HTTP请求 .2.服务器的网站服务系统(IIS)接收到该请求,先检查自己是否认识该类请求,如果认识就直接 ...
- RICOH C4502彩色打印机取消双面打印功能
参考下面步骤:
- SpringBoot第二十篇:初识ActiveMQ
本文是作者之前写的关于 ActiveMQ 的一篇文章.此处为了保证该系列文章的完整性,故此处重新引入. 一.消息中间件的介绍 介绍 消息队列 是指利用 高效可靠 的 消息传递机制 进行与平台无关的 数 ...
- CF 715 E. Complete the Permutations
CF 715 E. Complete the Permutations 题目大意:给定两个排列\(p,q\)的一部分.定义两个排列\(p,q\)的距离为使用最少的交换次数使得\(p_i=q_i\).对 ...
- 集合类源码(四)Collection之BlockingQueue(ArrayBlockingQueue, DelayQueue, LinkedBlockingQueue)
ArrayBlockingQueue 功能 全名 public class ArrayBlockingQueue<E> extends AbstractQueue<E> imp ...
- python 做词云图
#导入需要模块 import jieba import numpy as np import matplotlib.pyplot as plt from PIL import Image from w ...
- python正确使用异常处理机制
一.不要过度使用异常 不可否认,Python 的异常机制确实方便,但滥用异常机制也会带来一些负面影响.过度使用异常主要表现在两个方面: 把异常和普通错误混淆在一起,不再编写任何错误处理代码,而是以简单 ...
- ImageUtility辅助类
public class ImageUtility { #region 合并用户QR图片和用户头像 /// <summary> /// 合并用户QR图片和用户头像 /// </sum ...
- ASP.NET Core中使用MialKit实现邮件发送
# 导包 首先我们需要导入 MailKit NuGet包,NuGet安装包命令在下方拓展介绍中. # 引用命名空间 using MailKit.Net.Smtp; using MimeKit; # 邮 ...
- Ivanti的垃圾软件landesk
landesk是Ivanti公司推出的终端管理工具,这个工具垃圾就垃圾在无法卸载,进程杀不死.文件删不掉,奉劝大家千万不要安装这个软件.前些天公司的IT部门一直在催促员工安装这个软件,我一时糊涂安装了 ...