Java程序的工作机制Java对象都以单独的class文件存在java虚拟机将其载入并执行其虚拟机指令
Java虚拟机查找这些java对象 java虚拟机根据class path来查找java对象而虚拟机的class path又分为三层 bootstrapsunbootclasspath extension: javaextdirs application: javaclasspath 三个class path各有对应的classloader由上而下形成父子关系 当程序中调用new指令或者ClassLoaderload方法时其顺序如下 首先查看application的classloader中是否已有对应的class缓存如果有则返回并根据class分配内存如果没有接下一步 首先查看extension的classloader中是否已有对应的class缓存如果有则返回并根据class分配内存如果没有接下一步 首先查看bootstrap的classloader中是否已有对应的class缓存如果有则返回并根据class分配内存如果没有接下一步 由bootstrap的classloader在其class path中试图加载该class如果有则将该class放入cache中并返回如果没有接下一步 由extension的classloader在其class path中试图加载该class如果有则将该class放入cache中并返回如果没有接下一步 由application的classloader在其class path中试图加载该class如果有则将该class放入cache中并返回如果没有则抛出ClassNotFound的exception
Java虚拟机加载这些java对象 每个java虚拟机都在其启动时产生一个唯一的class heap并把所有的class instance都分配在其中其中每个类实例的信息又分两部分fields域和methods域每个类实例各自拥有fields但同一个类的不同实例共享methods
反射 JVM对反射的处理 简单例子代码 import javalangreflectInvocationHandler; import javalangreflectMethod; import javalangreflectInvocationTargetException; import javaioIOException;
public class Main { public static void main(String[] args){ TempImpl t = new TempImpl(temp); try { Method tTalk = tgetClass()getMethod(Talk new Class[]) ; tTalkinvoke(t null); } catch (NoSuchMethodException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } catch (IllegalAccessException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } catch (InvocationTargetException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } try { Systeminread(); } catch (IOException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } } } 复杂例子代码 import javalangreflectInvocationHandler; import javalangreflectMethod; import javalangreflectInvocationTargetException; import javaioIOException;
public class Main { public static void main(String[] args){ TempImpl t = new TempImpl(temp); TempImpl t = new TempImpl(temp); Temp temp = new Temp(); try { Method tTalk = tgetClass()getMethod(Talk new Class[]) ; Method tTalk = tgetClass()getMethod(Talk new Class[]) ; tTalkinvoke(t null); tTalkinvoke(t null); if(tTalkequals(tTalk)){ Systemoutprintln(equals); } else{ Systemoutprintln(not equals); } if(tTalk==tTalk){ Systemoutprintln(ref equals); } else{ Systemoutprintln(ref not equals); } tTalkinvoke(temp null); } catch (NoSuchMethodException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } catch (IllegalAccessException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } catch (InvocationTargetException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } try { Systeminread(); } catch (IOException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } } }
分析java虚拟机把每个methods当作一个执行单元该执行单元带有两种签名类签名和属性签名(publicstatic等) 反射的第一步验证签名的合法性验证通过后顺序执行该method中的指令当需要访问类实例的fields和传入参数时由虚拟机注入
动态代理 Sun对动态代理的说明 一个简单例子代码 动态代理的内部实现——代码生成 研究JDK源代码发现在Proxy的sun实现中调用了sunmiscProxyGenerator类的generateProxyClass( proxyName interfaces)方法其返回值为byte[]和class文件的内存类型一致于是做如下试验 public class ProxyClassFile{ public static void main(String[] args){ String proxyName = TempProxy; TempImpl t = new TempImpl(proxy); Class[] interfaces =tgetClass()getInterfaces(); byte[] proxyClassFile = ProxyGeneratorgenerateProxyClass( proxyName interfaces); File f = new File(classes/TempProxyclass); try { FileOutputStream fos = new FileOutputStream(f); foswrite(proxyClassFile); fosflush(); fosclose(); } catch (FileNotFoundException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } catch (IOException e) { eprintStackTrace(); //To change body of catch statement use File | Settings | File Templates } } } 运行该类到class文件夹下利用反编译技术发现原来其采用了代码生产技术 public interface Temp{ public void Talk(); public void Run(); } import javalangreflect*;
public final class TempProxy extends Proxy implements Temp{
private static Method m; private static Method m; private static Method m; private static Method m; private static Method m;
public TempProxy(InvocationHandler invocationhandler) { super(invocationhandler); }
public final void Run() { try { hinvoke(this m null); return; } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } }
public final String toString(){ try{ return (String)hinvoke(this m null); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } return ; }
public final int hashCode() { try { return ((Integer)hinvoke(this m null))intValue(); } catch(Error _ex) { } catch(Throwable throwable){ throw new UndeclaredThrowableException(throwable); } return ; }
public final void Talk(){ try{ hinvoke(this m null); return; } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } }
public final boolean equals(Object obj) { try { return ((Boolean)hinvoke(this m new Object[] { obj }))booleanValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } return false; }
static{ try{ m = ClassforName(Temp)getMethod(Run new Class[]); m = ClassforName(javalangObject)getMethod(toString new Class[]); m = ClassforName(javalangObject)getMethod(hashCode new Class[]); m = ClassforName(Temp)getMethod(Talk new Class[]); m = ClassforName(javalangObject)getMethod(equals new Class[] { ClassforName(javalangObject) }); } catch(NoSuchMethodException nosuchmethodexception) { throw new NoSuchMethodError(nosuchmethodexceptiongetMessage()); } catch(ClassNotFoundException classnotfoundexception) { throw new NoClassDefFoundError(classnotfoundexceptiongetMessage()); } } } |