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

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

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

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

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

  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. ROS融合IMU笔记

    ROS官网有一个叫robot_pose_ekf的包,是专门处理传感器融合的包,具体介绍:http://wiki.ros.org/robot_pose_ekf 其中主要功能是订阅主题包括odom(里程计 ...

  2. 到底如何选择PHP框架?Yii、ThinkPHP、laravel、CI.

    如果你是为了工作和就业,你应该选择框架以工作为目标,看公司里面未来招聘中用的最多的是什么框架.很简单的判断方式 很多朋友都不知道如何去选择框架,选择框架的时候就会很纠结.到底该学什么框架,选择什么框架 ...

  3. Prometheus Alertmanager 介绍详解

    Prometheus 之 Alertmanager 介绍详解 告警无疑是监控中非常重要的环节,虽然监控数据可视化了,也非常容易观察到运行状态.但我们很难做到时刻盯着监控,所以程序来帮巡检并自动告警,这 ...

  4. 【杂文】NOIP2018 蒟蒻自闭记

    [杂文]NOIP2018 蒟蒻自闭记 都 \(9102\) 年了,谁还记得 \(2018\) 年的事啊 \(QAQ\) . 还有两个月就要去参加首届 \(CSP\) 了. 想着如果再不记下去年那些事儿 ...

  5. 正在开发的JavaScript引擎有哪些?

    正在开发的JavaScript引擎有哪些? V8,用C++编写,开放源代码,由Google丹麦开发,是Google Chrome的一部分,也用于Node.js. JavaScriptCore,开放源代 ...

  6. Redis 实战搭建高可用架构

    前言:最近在看关于redis缓存方面的知识,今天就来个 Redis sentinel 高可用架构,实战开始之前,先看看sentinel的概念 什么是redis-sentinel Redis-Senti ...

  7. PIESDKDoNet二次开发配置注意事项

    在安装完PIESDK进行二次开发的过程中会遇到下面几种常见的开发配置问题,就写一个文档总结一下. 1.    新建项目无PIESDK模板问题 关于新建项目时候,找不到下图中的PIEMainApplic ...

  8. 阿里云监控RDS

    RDS性能监控API https://help.aliyun.com/document_detail/26280.html?spm=a2c4g.11186623.6.1576.341d7159uzLD ...

  9. 微信小程序页面调用自定义组件内的事件

    微信小程序页面调用自定义组件内的事件 page page.json { "usingComponents": { "my-component": ". ...

  10. 解决:ERROR 1067 (42000): Invalid default value for 'login_time'

    如图操作数据表的时候出现上图的错误 问题的原因就是出在timestamp的默认值不正确,针对以上问题的解决方案是:修改默认值为当前值. sql语言代码: Alter table user modify ...