Java 程序的工作机制: Java 对象都以单独的 class 文件存在, java 虚拟机将其载入并执行其虚拟机指令。 Java 虚拟机查找这些 java 对象: java 虚拟机根据 class path 来查找 java 对象,而虚拟机的 class path 又分为三层: bootstrap : sun.boot.class.path extension: java.ext.dirs application: java.class.path 三个 class path 各有对应的 classloader 。由上而下形成父子关系 当程序中调用 new 指令,或者 ClassLoader.load 方法时。其顺序如下: 1. 首先查看 application 的 classloader 中是否已有对应的 class 缓存,如果有则返回,并根据 class 分配内存。如果没有,接下一步。 2. 首先查看 extension 的 classloader 中是否已有对应的 class 缓存,如果有则返回,并根据 class 分配内存。如果没有,接下一步。 3. 首先查看 bootstrap 的 classloader 中是否已有对应的 class 缓存,如果有则返回,并根据 class 分配内存。如果没有,接下一步。 4. 由 bootstrap 的 classloader 在其 class path 中试图加载该 class ,如果有,则将该 class 放入 cache 中,并返回。如果没有,接下一步。 5. 由 extension 的 classloader 在其 class path 中试图加载该 class ,如果有,则将该 class 放入 cache 中,并返回。如果没有,接下一步。 6. 由 application 的 classloader 在其 class path 中试图加载该 class ,如果有,则将该 class 放入 cache 中,并返回。如果没有,则抛出 ClassNotFound 的 exception 。 Java 虚拟机加载这些 java 对象: 每个 java 虚拟机都在其启动时产生一个唯一的 class heap ,并把所有的 class instance 都分配在其中。其中每个类实例的信息又分两部分, fields 域和 methods 域。每个类实例各自拥有 fields ,但同一个类的不同实例共享 methods 反射 JVM 对反射的处理 简单例子代码:
复杂例子代码:
分析: java 虚拟机把每个 methods 当作一个执行单元。该执行单元带有两种签名:类签名和属性签名( public , static 等)。 反射的第一步,验证签名的合法性。验证通过后,顺序执行该 method 中的指令,当需要访问类实例的 fields 和传入参数时,由虚拟机注入。 动态代理 Sun 对动态代理的说明: 一个简单例子代码: 动态代理的内部实现——代码生成: 研究 JDK 源代码,发现在 Proxy 的 sun 实现中调用了 sun.misc.ProxyGenerator 类的 generateProxyClass( proxyName, interfaces) 方法,其返回值为 byte[] 和 class 文件的内存类型一致。于是做如下试验:
运行该类,到 class 文件夹下,利用反编译技术,发现原来其采用了代码生产技术:
|
|
来自: 碧海山城 > 《代理模式(与java的反射)》