1. 什么是Java反射,有什么用?反射使程序代码能够接入装载到JVM中的类的内部信息,允许在编写与执行时,而不是源代码中选定的类协作的代码,是以开发效率换运行效率的一种手段。这使反射成为构建灵活应用的主要工具。反射可以:调用一些私有方法,实现黑科技。比如双卡短信发送、设置状态栏颜色、自动挂电话等。实现序列化与反序列化,比如PO的ORM,Json解析等。实现跨平台兼容,比如JDK中的SocketImpl的实现通过xml或注解,实现依赖注入(DI),注解处理,动态代理,单元测试等功能。比如Retrofit、Spring或者Dagger2. Java Class文件的结构在*.class文件中,以Byte流的形式进行Class的存储,通过一系列Load,Parse后,Java代码实际上可以映射为下图的结构体,这里可以用javap命令或者IDE插件进行查看。——常量池(constant pool):类似于C中的DATA段与BSS段,提供常量、字符串、方法名等值或者符号(可以看作偏移定值的指针)的存放——access_flags: 对Class的flag修饰——this class/super class/interface: 一个长度为u2的指针,指向常量池中真正的地址,将在Link阶段进行符号解引。——filed: 字段信息,结构体如下method: 提供descriptor, access_flags, Code等索引,并指向常量池:它的结构体如下,详细在这里https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6以上具体内容可以参考——JVM文档https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html——周志明的《深入理解Java虚拟机》,少见的国内精品书籍——一些国外教程的解析http://viralpatel.net/blogs/tutorial-java-class-file-format-revealed/3. Java Class加载的过程Class的加载主要分为两步第一步通过ClassLoader进行读取、连结操作第二步进行Class的<clinit>()初始化。3.1. Classloader加载过程ClassLoader 用于加载、连接、缓存Class,可以通过纯Java或者native进行实现。在JVM的native代码中,ClassLoader内部维护着一个线 程安全的HashTable<String,Class>,用于实现对Class字节流解码后的缓存,如果HashTable中已经有了缓 存,则直接返回缓存;反之,在获得类名后,通过读取文件、网络上的class字节流反序列化为JVM中native的C结构体,接着malloc内存,并 将指针缓存在HashTable中。下面是非数组情况下ClassLoader的流程find/load: 将文件反序列化为C结构体。Class反序列化的流程link: 根据Class结构体常量池进行符号的解引。比如对象计算内存空间,创建方法表,native invoker,接口方法表,finalizer函数等工作。3.2. 初始化过程当ClassLoader加载Class结束后,将进行Class的初始化操作。主要执行<clinit()>的静态代码段与静态变量(取决于源码顺序)。具体参考如下:——http://www.programcreek.com/2013/01/when-and-how-a-java-class-is-loaded-and-initialized/——http://www.artima.com/insidejvm/ed2/lifetype.html
在完成初始化后,就是Object的构造<init>了,本文暂不讨论。4. 反射在native的实现反射在Java中可以直接调用,不过最终调用的仍是native方法,以下为主流反射操作的实现。4.1. Class.forName的实现Class.forName可以通过包名寻找Class对象,比如Class.forName("java.lang.String")。
在JDK的源码实现中,可以发现最终调用的是native方法forName0(),它在JVM中调用的实际是findClassFromClassLoader(),原理与ClassLoader的流程一样,具体实现已经在上面介绍过了。4.2. getDeclaredFields的实现在JDK源码中,可以知道class.getDeclaredFields()方法实际调用的是native方法getDeclaredFields0(),它在JVM主要实现步骤如下根据Class结构体信息,获取field_count与fields[]字段,这个字段早已在load过程中被放入了根据field_count的大小分配内存、创建数组将数组进行forEach循环,通过fields[]中的信息依次创建Object对象返回数组指针4.3. Method.invoke的实现以下为无同步、无异常的情况下调用的步骤创建Frame如果对象flag为native,交给native_handler进行处理在frame中执行java代码弹出Frame返回执行结果的指针4.4. class.newInstance的实现检测权限、预分配空间大小等参数创建Object对象,并分配空间通过Method.invoke调用构造函数(<init>())返回Object指针5. 附录5.1. JVM与源码阅读工具的选择初
次学习JVM时,不建议去看Android
Art、Hotspot等重量级JVM的实现,它内部的防御代码很多,还有android与libcore、bionic库紧密耦合,以及分层、内联甚至
能把编译器的语义分析绕进去,因此找一个教学用的、嵌入式小型的JVM有利于节约自己的时间。因为以前折腾过OpenWrt,听过有大神推荐过
jamvm,只有不到200个源文件,非常适合学习。在工具的选择上,个人推荐SourceInsight。对比了好几个工具clion,vscode,sublime,sourceinsight,只有sourceinsight对索引、符号表的解析最准确。5.2. 关于几个ClassLoader参考http://stackoverflow.com/questions/1771679/difference-between-threads-context-class-loader-and-normal-classloader。ClassLoader0:native的classloader,在JVM中用C写的,用于加载rt.jar的包,在Java中为空引用。ExtClassLoader: 用于加载JDK中额外的包,一般不怎么用AppClassLoader: 加载自己写的或者引用的第三方包,这个最常见例子如下最后就是getContextClassLoader(),它在Tomcat中使用,通过设置一个临时变量,可以向子类ClassLoader去加载,而不是委托给ParentClassLoader最后还有一些自定义的ClassLoader,实现加密、压缩、热部署等功能,这个是大坑,晚点再开。5.3. 反射是否慢?在Stackoverflow上认为反射比较慢的程序员主要有如下看法验证等防御代码过于繁琐,这一步本来在link阶段,现在却在计算时进行验证产生很多临时对象,造成GC与计算时间消耗由于缺少上下文,丢失了很多运行时的优化,比如JIT(它可以看作JVM的重要评测标准之一)当然,现代JVM也不是非常慢了,它能够对反射代码进行缓存以及通过方法计数器同样实现JIT优化,所以反射不一定慢。更重要的是,很多情况下,你自己的代码才是限制程序的瓶颈。因此,在开发效率远大于运行效率的的基础上,大胆使用反射,放心开发吧。

Java反射在JVM的实现的更多相关文章

  1. java反射并不是什么高深技术,面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象

    java反射并不是什么高深技术,面向对象语言都有这个功能. 面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象,去获取类相关的信息 2.利用java反射可以调用类 ...

  2. 《深入理解Java虚拟机》- JVM是如何实现反射的

    Java反射学问很深,这里就浅谈吧.如果涉及到方法内联,逃逸分析的话,我们就说说是什么就好了.有兴趣的可以去另外看看,我后面可能也会写一下.(因为我也不会呀~) 一.Java反射是什么? 反射的核心是 ...

  3. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  4. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  5. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  6. java反射 之 反射基础

    一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...

  7. 【转】Java反射 之 反射基础

    一.反射 反射:Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...

  8. Java反射机制专题

    ·Java Reflection Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方 ...

  9. java反射机制深入详解

    java反射机制深入详解  转自:http://www.cnblogs.com/hxsyl/archive/2013/03/23/2977593.html 一.概念 反射就是把Java的各种成分映射成 ...

随机推荐

  1. Matlab之画图

    1.设置对数坐标 set(gca,'XScale','log','YScale','log'); 2.加网格 grid on; 3.加log对齐网格 set(gca,'XScale','log','Y ...

  2. css子元素的margin-top为何会影响父元素

    详细内容请点击 这个问题困惑了很久,虽然没有大碍早就摸出来怎么搞定它,但始终不明白原因出在哪里,如果只是IE有问题我也不会太在意,可问题是所有上等浏览器都表现如此,这样叫我怎能安心?今天总算下狠心查出 ...

  3. @font-face 用字体画图标

    HTML <body> <!-- ul.layout>li*5>a[href=#]>i.icon --> <!-- Sublime Text 快捷拼写 ...

  4. 零碎记录Hadoop平台各组件使用

    >20161011 :数据导入研究    0.sqoop报warning,需要安装accumulo:    1.下载Microsoft sql server jdbc, 使用ie下载,将42版j ...

  5. CefSharp 发布后在客户机上报找不到dll的问题

    两个因素:一是与项目平台属性的选择要一致二是需要安装CefSharp对应的的VC++可发行组件包(用包管理器引用了此DLL后,会有一个readme.txt,上面详细介绍了CefSharp所需要的环境要 ...

  6. 二维码zxing源码分析(二)decode部分

           在上一篇博客中分析了zxing怎么打开摄像头,并且扫描结果,那么扫描之后的数据呢,是不是就要解析了呢,那我们看一下zxing怎么解析这个数据的.       上一篇博客地址ZXING源码 ...

  7. SQL Server 2008 报表服务入门

    目录 报表服务的安装与配置 开发报表的过程 报表制作实例 一.报表服务的安装与配置 1. 报表服务的组件 2. 报表服务 2008 的安装 2.1在SQL Server 2008上安装报表服务有两种方 ...

  8. linux系统man查询命令等级与意义

    代号 意义 1 可执行程序和一般shell命令 2 系统调用函数 3 库函数 4 设备配置文件,通常在/dev下 5 配置文件,/ec下 6 游戏 7 协议及杂项 8 管理员命令 9 与内核相关

  9. python 中range与xrange的区别

    先来看看range与xrange的用法介绍 help(range)Help on built-in function range in module __builtin__: range(...) r ...

  10. 《DDNS服务器的搭建和案例解决方法》

    DDNS原理:DNS + DHCP =DDNS DHCP负责ip解析,和分配给客户机ip,ip为随机数. DNS负责域名解析,A记录里记录了每个ip对应的域名. 客户端ip肯定是变化的,不可能一直使用 ...