<o:p>(从csdn的blog转来) </o:p>
Java 程序的工作机制: Java 对象都以单独的 class 文件存在, java 虚拟机将其载入并执行其虚拟机指令。
<o:p> </o:p>
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 。
<o:p> </o:p>
Java 虚拟机加载这些 java 对象:
每个 java 虚拟机都在其启动时产生一个唯一的 class heap ,并把所有的 class instance 都分配在其中。其中每个类实例的信息又分两部分, fields 域和 methods 域。每个类实例各自拥有 fields ,但同一个类的不同实例共享 methods
<o:p> </o:p>
反射
JVM 对反射的处理
简单例子代码:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import java.io.IOException; <o:p> </o:p> public class <st1:place w:st="on">Main</st1:place> { public static void main(String[] args){ TempImpl t1 = new TempImpl("temp1"); try { Method t1Talk = t1.getClass().getMethod("Talk", new Class[0]) ; t1Talk.invoke(t1, null); } catch (NoSuchMethodException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } catch (IllegalAccessException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } catch (InvocationTargetException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } try { System.in.read(); } catch (IOException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } } |
复杂例子代码:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import java.io.IOException; <o:p> </o:p> public class <st1:place w:st="on">Main</st1:place> { public static void main(String[] args){ TempImpl t1 = new TempImpl("temp1"); TempImpl t2 = new TempImpl("temp2"); Temp2 temp2 = new Temp2(); try { Method t1Talk = t1.getClass().getMethod("Talk", new Class[0]) ; Method t2Talk = t2.getClass().getMethod("Talk", new Class[0]) ; t1Talk.invoke(t2, null); t2Talk.invoke(t1, null); if(t1Talk.equals(t2Talk)){ System.out.println("equals"); } else{ System.out.println("not equals"); } if(t1Talk==t2Talk){ System.out.println("ref equals"); } else{ System.out.println("ref not equals"); } t2Talk.invoke(temp2, null); } catch (NoSuchMethodException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } catch (IllegalAccessException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } catch (InvocationTargetException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } try { System.in.read(); } catch (IOException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } } |
<o:p> </o:p>
分析: java 虚拟机把每个 methods 当作一个执行单元。该执行单元带有两种签名:类签名和属性签名( public , static 等)。 反射的第一步,验证签名的合法性。验证通过后,顺序执行该 method 中的指令,当需要访问类实例的 fields 和传入参数时,由虚拟机注入。
<o:p> </o:p>
动态代理
Sun 对动态代理的说明:
一个简单例子代码:
动态代理的内部实现——代码生成:
研究 JDK 源代码,发现在 Proxy 的 sun 实现中调用了 sun.misc.ProxyGenerator 类的 generateProxyClass( proxyName, interfaces) 方法,其返回值为 byte[] 和 class 文件的内存类型一致。于是做如下试验:
public class ProxyClassFile{ public static void main(String[] args){ String proxyName = "TempProxy"; TempImpl t = new TempImpl("proxy"); Class[] interfaces =t.getClass().getInterfaces();
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces); File f = new File("classes/TempProxy.class"); try { FileOutputStream fos = new FileOutputStream(f); fos.write(proxyClassFile); fos.flush(); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } catch (IOException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } } |
运行该类,到 class 文件夹下,利用反编译技术,发现原来其采用了代码生产技术:
<o:p> </o:p>
public interface Temp{<o:p></o:p> public void Talk();<o:p></o:p> public void Run();<o:p></o:p> }<o:p></o:p> |
import java.lang.reflect.*;<o:p></o:p> <o:p> </o:p> public final class TempProxy extends Proxy<o:p></o:p> implements Temp{<o:p></o:p> <o:p> </o:p> private static Method m4;<o:p></o:p> private static Method m2;<o:p></o:p> private static Method m0;<o:p></o:p> private static Method m3;<o:p></o:p> private static Method m1;<o:p></o:p> <o:p> </o:p> public TempProxy(InvocationHandler invocationhandler) {<o:p></o:p> super(invocationhandler);<o:p></o:p> }<o:p></o:p> <o:p> </o:p> public final void Run() {<o:p></o:p> try {<o:p></o:p> h.invoke(this, m4, null);<o:p></o:p> return;<o:p></o:p> }<o:p></o:p> catch(Error _ex) { }<o:p></o:p> catch(Throwable throwable) {<o:p></o:p> throw new UndeclaredThrowableException(throwable);<o:p></o:p> }<o:p></o:p> }<o:p></o:p> <o:p> </o:p> public final String toString(){<o:p></o:p> try{<o:p></o:p> return (String)h.invoke(this, m2, null);<o:p></o:p> }<o:p></o:p> catch(Error _ex) { }<o:p></o:p> catch(Throwable throwable) {<o:p></o:p> throw new UndeclaredThrowableException(throwable);<o:p></o:p> }<o:p></o:p> return "";<o:p></o:p> }<o:p></o:p> <o:p> </o:p> public final int hashCode() {<o:p></o:p> try {<o:p></o:p> return ((Integer)h.invoke(this, m0, null)).intValue();<o:p></o:p> }<o:p></o:p> catch(Error _ex) { }<o:p></o:p> catch(Throwable throwable){<o:p></o:p> throw new UndeclaredThrowableException(throwable);<o:p></o:p> }<o:p></o:p> return 123;<o:p></o:p> }<o:p></o:p> <o:p> </o:p> public final void Talk(){<o:p></o:p> try{<o:p></o:p> h.invoke(this, m3, null);<o:p></o:p> return;<o:p></o:p> }<o:p></o:p> catch(Error _ex) { }<o:p></o:p> catch(Throwable throwable) {<o:p></o:p> throw new UndeclaredThrowableException(throwable);<o:p></o:p> }<o:p></o:p> }<o:p></o:p> <o:p> </o:p> public final boolean equals(Object obj) {<o:p></o:p> try {<o:p></o:p> return ((Boolean)h.invoke(this, m1, new Object[] {<o:p></o:p> obj<o:p></o:p> })).booleanValue();<o:p></o:p> }<o:p></o:p> catch(Error _ex) { }<o:p></o:p> catch(Throwable throwable) {<o:p></o:p> throw new UndeclaredThrowableException(throwable);<o:p></o:p> }<o:p></o:p> return false;<o:p></o:p> }<o:p></o:p> <o:p> </o:p> static{<o:p></o:p> try{<o:p></o:p> m4 = Class.forName("Temp").getMethod("Run", new Class[0]);<o:p></o:p> m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);<o:p></o:p> m0 = Class.forName("java.lang.Object").getMethod("hashCode", ne |