JVM,反射与动态代理

 
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 对反射的处理
简单例子代码:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.io.IOException;
 
public class Main {
    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;
 
public class Main {
    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.
        }
    }
}
 
分析: java 虚拟机把每个 methods 当作一个执行单元。该执行单元带有两种签名:类签名和属性签名( public , static 等)。 反射的第一步,验证签名的合法性。验证通过后,顺序执行该 method 中的指令,当需要访问类实例的 fields 和传入参数时,由虚拟机注入。
 
动态代理
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 文件夹下,利用反编译技术,发现原来其采用了代码生产技术:
 
public interface Temp{
       public void Talk();
       public void Run();
}
import java.lang.reflect.*;
 
public final class TempProxy extends Proxy
    implements Temp{
 
    private static Method m4;
    private static Method m2;
    private static Method m0;
    private static Method m3;
    private static Method m1;
 
    public TempProxy(InvocationHandler invocationhandler)   {
        super(invocationhandler);
    }
 
    public final void Run()    {
        try {
            h.invoke(this, m4, null);
            return;
        }
        catch(Error _ex) { }
        catch(Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }
 
    public final String toString(){
        try{
            return (String)h.invoke(this, m2, null);
        }
        catch(Error _ex) { }
        catch(Throwable throwable)  {
            throw new UndeclaredThrowableException(throwable);
        }
        return "";
    }
 
    public final int hashCode() {
        try {
            return ((Integer)h.invoke(this, m0, null)).intValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable){
            throw new UndeclaredThrowableException(throwable);
        }
        return 123;
    }
 
    public final void Talk(){
        try{
            h.invoke(this, m3, null);
            return;
        }
        catch(Error _ex) { }
        catch(Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }
 
    public final boolean equals(Object obj) {
        try {
            return ((Boolean)h.invoke(this, m1, new Object[] {
                obj
            })).booleanValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
        return false;
    }
 
    static{
        try{
     m4 = Class.forName("Temp").getMethod("Run", new Class[0]);
     m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
     m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
     m3 = Class.forName("Temp").getMethod("Talk", new Class[0]);
     m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
                Class.forName("java.lang.Object")
            });
        }
        catch(NoSuchMethodException nosuchmethodexception) {
           throw new NoSuchMethodError(nosuchmethodexception.getMessage());
        }
        catch(ClassNotFoundException classnotfoundexception) {
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());
        }
    }
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值