反射和类加载器

来源:互联网 发布:msbs步枪 知乎 编辑:程序博客网 时间:2024/05/22 18:09

转载请注明:http://blog.csdn.net/hel_wor/article/details/50375054

当初看了几本书后因为觉得反射,多态,动态链接有共同的地方,所以对底层有了好奇。

终于能动手写这篇博客了,前前后后的逻辑感觉能走通了。
反射是在运行期动态的获取某个类的成员和方法。
反射和类加载器的关系,即是我们在反射调用某个类时,这个类会被类加载器加载一次,第一个问题,如何去加载这个类,第二个问题,谁来加载这个类。

加载的这个类时通过加载这个类的class文件完成的,要找到这个class文件,我们需要这个类的名字,在java虚拟机规范中有提到这个名字是class的二进制名称。二进制名称也叫全限定名,其命名逻辑和电脑本地上某个文件的路径类似,比如类加载器的二进制名称就为java/lang/ClassLoader。class文件的二进制名称被放在class文件常量池的Constant_Utf8_info结构中。如果没有找到这个二进制名称的class文件,则会报出ClassNotFound。

在之前的博客里提到过,出于安全原因,不同类加载器加载的类是不允许相互可见的,又相互引用关系的class文件会被同一类加载器加载,使它们可相互访问,也就是一个类加载器对应一个命名空间;由此,‘我’在经过反射调用对象N时,加载N的class文件的类加载器,即为加载‘我’的类加载器。

顺便记录一下如何找到加载‘我’的类加载器。
在sun/reflect/Reflction中:
这里写图片描述

GetCallerClass()就是获取发起请求的类的方法。
关于@CallerSensitive这个注解JVM注解@CallSensitive有提到过,这个注解的目的也是为了帮助JVM找到真正的‘我’,即真正的请求发起者。

前面大致的内容很宽泛的叙述了。关于详细的反射过程在莫枢的博客里有源代码描述了,这一步我就不重复了,在莫枢没讲到的地方,关于最后提到的类MethodAccessorGenerator,generate()函数前半段代码是在构造class文件,在后半部分有下面这段代码:
这里写图片描述

再看JDK API1.6.0 中对defineClass的描述:
这里写图片描述

对应这个函数签名的defineClass()在调用结束后,会返回这个类的实例,也即是我们请求反射的类,至此,类的反射加载逻辑就完成了。

0 0