JVM的反射实现
java的反射机制
java的反射机制是在运行状态中,对于任意一个类(Class)都能知道他的属性(Field)和方法(Method),对于任意一个对象都能够调用它的方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。它允许正在运行的java程序观测甚至是修改程序的动态行为。
在java中实现反射最重要的一步也就是第一步是获得Class对象,得到该对象后可通过该对象调用相应的方法获取该类中的属性方法,以及调用该类中的方法。
Java中反射有如下几种实现方式:
1、通过Class.forName()方法加载字符串,就可以得到该字符串做代表的Class对象。
如:Class<?> clazz = Class.forName("java.lang.String")就可以得到String类的Class对象。值得注意的是,字符串必须是类的全名,即包名+类名。
下边的代码是Struts配置文件struts.xml中的一个action的配置。
<action name="registe" class="cn.com.test.struts2.RegisteAction">
<result>/registeResult.jsp</result>
<result name="input">/registe2.jsp</result>
</action>
服务器就是通过class属性给出的类的全命名class="cn.com.test.struts2.RegisteAction"的字符串来得到对象的,就是反射机制RegisteAction的。然后再去调用这个类中execute()方法。
2、通过类名调用class属性得到该类的Class对象。
Class<?> clazz = String.class也可以得到String类的Class对象。
3、调用实例的getClass()方法。
Class<?> clazz = date.getClass();
如:Class<?> clazz = Integer.TYPE;
我们可以通过Class对象枚举该类中的所有方法,还可以通过Method.setAccessible(位于java.lang.reflect包,该方法继承自AccessibleObject)绕过java语言的访问权限,在私有方法所在类之外的地方调用该方法。
反射在java中的应用
1、java集成开发环境,每当我们敲入点号时,IDE便会根据点号前的内容,动态展示可以访问的字段和方法。
2、java调试器,它能够在调试过程中枚举某一对象所有字段的值。
3、web开发中,我们经常接触到各种配置的通用框架。为保证框架的可扩展性,他往往借助java的反射机制。例如Spring框架的依赖反转(IOC)便是依赖于反射机制。
反射调用的实现Mehod.invoke
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
你会发现,它实际上是委派给 MethodAccessor 来处理。MethodAccessor 是一个接口,它有两个实现:一个通过本地方法来实现反射调用,另一个使用了委派模式(这里我们称委派实现)。
每个 Method 实例的第一次反射调用都会生成一个委派实现,他所委派的具体实现便是一个本地实现。当进入JVM内部后,我们便拥有了Mehod 实例所指向方法的具体地址。这时反射调用无非就是将传入的参数准备好,然后调用进入目标方法。
反射调用先是调用了Method.invoke, 然后进入委派实现(DelegatingMethodAccessorImpl),再进入本地实现(NativeMethodAccessorImpl),最后到达目标方法。
调用了Method.invoke之后,先进行访问权限检查,再获取MethodAccessor对象,并调用MethodAccessor.invoke方法。MethodAccessor被同名Method所共享,由ReflectionFactory创建。创建机制采用一种名为inflation的方式:如果该方法的调用<=15,会创建本地实现,他的实现就是直接调用native方法实现反射,如果该方法的累计调用次数>15,会创建由字节码组装而成的MethodAccessorImpl。(是否采用inflation机制和15这个数字可以在jvm参数中调整)。
性能
通过JNI(java本地接口)调用native方法初始化更快,但是对优化有阻碍作用。随着调用次数的增多,使用动态实现可以直接以java调用的方式来实现反射,发挥了java即时编译的优化作用。
java反射调用效率慢的原因:
1、接口的通用性,java的invoke方法是传object和object[]数组的。基本参数类型需要装箱和拆箱,产生大量额外的对象和内存开销,频繁促发GC。
2、编译器难以对动态调用的代码提前做优化比如方法内联。
3、反射需要按名检索类和方法,有一定的时间开销。
JVM的反射实现的更多相关文章
- Java jvm 类加载 反射
		Java 底层 jvm,类加载,反射 Java语言是跨平台语言,一段java代码,经过编译成class文件后,能够在不同系统的服务器上运行:因为java语言中有虚拟机jvm,才有了跨平台,java为了 ... 
- JVM总结-反射
		反射是 Java 语言中一个相当重要的特性,它允许正在运行的 Java 程序观测,甚至是修改程序的动态行为. 举例来说,我们可以通过 Class 对象枚举该类中的所有方法,我们还可以通过 Method ... 
- JVM 学习(一)反射、垃圾回收、异常处理--- 2019年4月
		1.JVM 基础知识点 JVM 虚拟机包含了:自动内存管理器.垃圾回收(垃圾回收调优). 执行顺序:Java 代码 --- .class 字节码文件(加载到虚拟机中) --- Java 类放在方法区中 ... 
- 《深入理解Java虚拟机》- JVM是如何实现反射的
		Java反射学问很深,这里就浅谈吧.如果涉及到方法内联,逃逸分析的话,我们就说说是什么就好了.有兴趣的可以去另外看看,我后面可能也会写一下.(因为我也不会呀~) 一.Java反射是什么? 反射的核心是 ... 
- JVM 第一次学习总结(2019年4月)
		1.内存模型 起源:在计算机系统,加入了一层读写速度尽可能接近处理器运算速度的高速缓存来作为内存和处理器之间的缓冲. 问题:缓存一致性.在多处理器系统中,每个处理器都有自己的高速缓存(抽象为工作内存) ... 
- JVM反调调用优化,导致发生大量异常时log4j2线程阻塞
		背景 在使用log4j2打日志时,当发生大量异常时,造成大量线程block问题的问题. 一个关于log4j2的高并发问题:https://blog.fliaping.com/a-high-concur ... 
- jvm  命令使用调优  通过jstat、jmap对java程序进行性能调优
		转载:http://blog.csdn.net/jerry024/article/details/8507589 转载: https://blog.csdn.net/zhaozheng7758/art ... 
- 反射之深入理解Constructor原理
		.katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ... 
- 深入理解JVM(学习过程)
		这,仅是我学习过程中记录的笔记.确定了一个待研究的主题,对这个主题进行全方面的剖析.笔记是用来方便我回顾与学习的,欢迎大家与我进行交流沟通,共同成长.不止是技术. 2020年02月06日22:43:0 ... 
随机推荐
- python的内存管理与垃圾回收机制学习
			一.python内存申请: 1.python的内存管理分为六层:最底的两层有OS控制.第三层是调用C的malloc和free等进行内存控制.第四层第五层是python的内存池.最上层使我们接触的直接对 ... 
- 使用as3crypto在Flex中实现AES加密
			要在Flex中实现AES加密,可以通过as3crypto实现.但是as3crypto本身的用法比较复杂,一般是封装一下再调用. 下面是9RIA上的一篇文章给出的一个实现,使用中稍感不方便(见注释): ... 
- go练习3 --map的操作
			func T2_1() { // 键值string , 值 int 类型 m1 := map[string]int{} //添加一个元素 m1["str1&q ... 
- Android中textView自动识别电话号码,电子邮件,网址(自动加连接)
			extends:http://blog.csdn.net/wx_962464/article/details/8471195 其实这个是很简单的,在android中已经为我们实现了,但是我估计很多人都 ... 
- This function has none of DETERMINISTIC, NO SQL
			错误信息: [Err] 1418 - This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declara ... 
- 无法远程访问Mysql
			1.故障状态 [root@server02 ~]# mysql -utuser -h192. -p Enter password: ERROR (HY000): Can't connect to My ... 
- jQuery --- 利用a标签的download属性下载文件!
			最近遇到一个项目,需要有点击下载文件的功能. 由于文件格式是多种的,对于 rar / zip / rtf / doc / xlsx / jpg等. 点击下载有的是直接跳转到后进行下载,但有的是打开进行 ... 
- PreparedStatement vs Statement
			Statement和PreparedStatement之间的区别 1.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程 2.使用 Statemen ... 
- python为什么需要reload(sys)后设置编码
			python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报这样的错UnicodeDecodeError: 'ascii' codec can't deco ... 
- CF1028E Restore Array 构造
			正解:构造 解题报告: 传送门! 是的灵巧还在写构造,,,不知道484我做题太慢的缘故我感觉我做了好久的构造了然而一半的题目都没做完QAQ 要哭出来了QAQ 然后说下这题的解法,开始花了这——么的时间 ... 
