《红楼梦》第十二回,贾瑞因痴迷王熙凤,被王熙凤折腾的眼看就快不行了。当然这里面是没有多少爱的,完全因王熙凤的美貌而起。就在这时来了一个跛足道人,带来了一面宝镜,说能治好贾瑞的病。当然这可不是一面普通的镜子,而是由警幻仙子做制。并且道人还告诫贾瑞,这面镜子专治邪思妄动之症,有济世保生之功。所以带他到世上,单与那些聪明俊杰,风雅王孙等看照。千万不可照正面,只照他的背面。

  贾瑞先是依着跛足道人的话,照的背面。可是却看到一个骷髅立在里面,把贾瑞吓了个半死。这时贾瑞以为道士骗他,赶忙照了正面,这下看到了美貌的王熙凤,贾瑞满意极了。可是他的命却没有了。

  正面的那个骷髅,正是病入膏肓的贾瑞自己,可是他却不敢相信那就是他自己现在的形象。他宁愿相信假的,也不愿相信真的。跛足道人明明叫贾瑞照背面,可是贾瑞却偏偏喜欢照正面。那是因为正面有贾瑞喜欢的东西。这时,再高明的医生也救不了他了。可想曹雪芹写到这里,虽说用的是风趣幽默的语言,从中却能看出他的无奈。

  每天清晨傍晚,当我们站在镜子时前可曾想过,摘掉喜好的有色眼镜打开自己的心肺肠肝,镜中是否还是自己当初想要的样子。

  以铜为镜正衣冠、以史为镜知兴替、以人为镜明得失。人类需要镜子去看清自己、看清时间、看清取舍,同样的是 类也需要。

  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. (1)基于tcp协议的编程模型 (2)tcp协议和udp协议的比较 (3)基于udp协议的编程模型 (4)反射机制

    1.基于tcp协议的编程模型(重中之重)1.1 编程模型服务器: (1)创建ServerSocket类型的对象,并提供端口号: (2)等待客户端的连接请求,调用accept()方法: (3)使用输入输 ...

  2. oop klass

    https://www.infoq.com/articles/Introduction-to-HotSpot 借助HotSpot SA来一窥PermGen上的对象 找出栈上的指针/引用 虚拟机随谈(一 ...

  3. PBR Step by Step(四)Lambertian反射模型

    光照可分为局部光照和全局光照. 局部光照:直接照射到物体表面的光照 全局光照:物体表面受周围环境影响的光照 左图中点x接收到周围环境的光线照射,来自周围表面的反射光照称为全局光照:右图中点x接收来自太 ...

  4. PHP API反射实例

    *反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用.其用途如:自动加载插件,自动生成文档,甚至可用来扩充PHP语言.php反射api由若干类组成,可帮助我们用来 ...

  5. HotSpot的类模型(2)

    在前一篇文章 HotSpot的二分模型中已经讲过,HotSpot采用了OOP-Klass模型描述Java的类和对象.Klass模型采用Klass类及相关子类来表示具体的Java类,可以理解这些类为Ja ...

  6. HotSpot二分模型(1)

    HotSpot采用了OOP-Klass模型来描述Java类和对象.OOP(Ordinary Object Pointer)指的是普通对象指针,而Klass用来描述对象的具体类型. 那么为何要设计这样一 ...

  7. HotSpot源码分析之类模型

    HotSpot采用了OOP-Klass模型描述Java的类和对象.Klass模型采用Klass类及相关子类的对象来描述具体的Java类.一般HotSpot JVM 在加载Java的Class 文件时, ...

  8. 【夯实PHP基础】PHP的反射机制

    本文地址 分享提纲: 1. 介绍 2. 具体例子 2.1 创建Persion类 2.2 反射过程 2.3 反射后使用 1. 介绍 -- PHP5添加了一项新的功能:Reflection.这个功能使得p ...

  9. php反射机制

    PHP5添加了一项新的功能:Reflection.这个功能使得phper可以reverse-engineer class, interface,function,method and extensio ...

随机推荐

  1. Vue官方文档笔记(二)

    23.$refs是什么东东? 通过在标签上设置ref属性,然后在Vue实例方法中可以通过$refs拿到这些标签,如: <input ref="input"> metho ...

  2. rdd 基本操作

    package com.jason.example import org.apache.spark.rdd.RDD class RddTest extends SparkInstance { val ...

  3. Python处理数据集-2

    原数据集的数据格式: 每行为:(test_User, test_Item) negativeItem1 negativeItem2 negativeItem3 …… negativeItem99 即每 ...

  4. 关于wepy小程序图片显示问题

    如果图片资源在本地,用background-image 是无法找到本地资源的,只能通过image标签用src进行引入: 图片资源在服务器上,用背景图片和image进行引入,在安卓真机上测试是没有问题的 ...

  5. vins_fusion学习笔记

    Vins-Fusion源码:https://github.com/HKUST-Aerial-Robotics/VINS-Fusion 摘要 应项目需要,侧重学习stereo+gps融合 转载几篇写的比 ...

  6. pandas的使用(6)离散化和合并

    pandas的使用(6)离散化和合并

  7. Rider中Winform开发支持预览(5)

    1.Rider .netCore3.0 winform设计器支持预览,这点vs目前还不支持. 2.不过winform下控件选择工具栏都是没有图标的

  8. mongodb数据库环境配置

    数据是每一前端人员必定接触的一样,所有的数据都是后端来编写,如果自己想练习项目,却没有数据,而是写一些假数据,去编写,或者通过json-server搭建一个数据,今天我们就通过MongoDB来搭建一个 ...

  9. JavaIO学习:转换流

    转换流 1.涉及到的类 InputStreamReader:将InputStream转换为Reader OutputStreamWriter:将Writer转换为OutputStream 2.构造器 ...

  10. nginx 反向代理时丢失端口的解决方案(转)

    今天,配置nginx反向代理时遇到一个问题,当设置nginx监听80端口时转发请求没有问题.但一旦设置为监听其他端口,就一直跳转不正常:如,访问欢迎页面时应该是重定向到登录页面,在这个重定向的过程中端 ...