简单讨论JVM的class加载机制,给出两个反射的例子代码并分析工作原理,并给出了sun的动态代理实现原理——代码生成
JavaVM,反射与动态代理
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文件夹下,利用反编译技术,发现原来其采用了代码生产技术:
|
|
来自: shaobin0604@1... > 《Java》