科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道JVM,反射与动态代理

JVM,反射与动态代理

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

简单讨论JVM的class加载机制,给出两个反射的例子代码并分析工作原理,并给出了sun的动态代理实现原理——代码生成。

作者:Anders小明 来源:CSDN 2008年3月17日

关键字: 反射 JVM java

  • 评论
  • 分享微博
  • 分享邮件

Java程序的工作机制:Java对象都以单独的class文件存在,java虚拟机将其载入并执行其虚拟机指令。

 

Java虚拟机查找这些java对象:

java虚拟机根据class path来查找java对象,而虚拟机的class path又分为三层:

bootstrapsun.boot.class.path

extension: java.ext.dirs

application: java.class.path

三个class path各有对应的classloader。由上而下形成父子关系

当程序中调用new指令,或者ClassLoader.load方法时。其顺序如下:

1.       首先查看applicationclassloader中是否已有对应的class缓存,如果有则返回,并根据class分配内存。如果没有,接下一步。

2.       首先查看extensionclassloader中是否已有对应的class缓存,如果有则返回,并根据class分配内存。如果没有,接下一步。

3.       首先查看bootstrapclassloader中是否已有对应的class缓存,如果有则返回,并根据class分配内存。如果没有,接下一步。

4.       bootstrapclassloader在其class path中试图加载该class,如果有,则将该class放入cache中,并返回。如果没有,接下一步。

5.       extensionclassloader在其class path中试图加载该class,如果有,则将该class放入cache中,并返回。如果没有,接下一步。

6.       applicationclassloader在其class path中试图加载该class,如果有,则将该class放入cache中,并返回。如果没有,则抛出ClassNotFoundexception

 

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当作一个执行单元。该执行单元带有两种签名:类签名和属性签名(publicstatic等)。 反射的第一步,验证签名的合法性。验证通过后,顺序执行该method中的指令,当需要访问类实例的fields和传入参数时,由虚拟机注入。

 

动态代理

Sun对动态代理的说明:

一个简单例子代码:

动态代理的内部实现——代码生成:

研究JDK源代码,发现在Proxysun实现中调用了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());

        }

    }

}

 

 

    • 评论
    • 分享微博
    • 分享邮件
    闂傚倸鍊搁崐椋庢閿熺姴鐭楅幖娣妼缁愭鏌¢崶鈺佷汗闁哄閰i弻鏇$疀鐎n亞浠炬繝娈垮灠閵堟悂寮婚弴锛勭杸閻庯綆浜栭崑鎾诲冀椤撱劎绋忛梺璺ㄥ櫐閹凤拷

    濠电姷鏁告慨鐑姐€傛禒瀣劦妞ゆ巻鍋撻柛鐔锋健閸┾偓妞ゆ巻鍋撶紓宥咃躬楠炲啫螣鐠囪尙绐為梺褰掑亰閸撴盯鎮惧ú顏呪拺闂傚牊鍗曢崼銉ョ柧婵犲﹤瀚崣蹇旂節婵犲倻澧涢柛瀣ㄥ妽閵囧嫰寮介妸褋鈧帡鏌熼挊澶婃殻闁哄瞼鍠栭幃婊堝煛閸屾稓褰嬮柣搴ゎ潐濞叉ê鐣濈粙璺ㄦ殾闁割偅娲栭悡娑㈡煕鐏炲墽鐭嬫繛鍫熸倐濮婄粯鎷呯粵瀣異闂佹悶鍔嬮崡鍐茬暦閵忋倕鍐€妞ゆ劑鍎卞皬闂備焦瀵х粙鎴犫偓姘煎弮瀹曚即宕卞Ο闀愮盎闂侀潧鐗嗛幊搴㈡叏椤掆偓閳规垿鍩ラ崱妞剧凹濠电姰鍨洪敋閾荤偞淇婇妶鍛櫤闁稿鍊圭换娑㈠幢濡纰嶉柣搴㈣壘椤︾敻寮诲鍫闂佸憡鎸鹃崰搴敋閿濆鏁嗗〒姘功閻绻涢幘鏉戠劰闁稿鎹囬弻锝呪槈濞嗘劕纾抽梺鍝勬湰缁嬫垿鍩為幋锕€宸濇い鏇炴噺閳诲﹦绱撻崒娆戝妽妞ゃ劌鎳橀幆宀勫磼閻愰潧绁﹂柟鍏肩暘閸斿矂鎮為崹顐犱簻闁圭儤鍨甸鈺呮倵濮橆剦妲归柕鍥у瀵粙濡歌閸c儳绱撴担绛嬪殭婵☆偅绻堝濠氭偄绾拌鲸鏅i悷婊冪Ч閹﹢鎳犻鍌滐紲闁哄鐗勯崝搴g不閻愮儤鐓涢悘鐐跺Г閸犳﹢鏌℃担鐟板鐎规洜鍠栭、姗€鎮╅搹顐ら拻闂傚倷娴囧畷鍨叏閹惰姤鈷旂€广儱顦崹鍌炴煢濡尨绱氶柨婵嗩槸缁€瀣亜閺嶃劎鈽夋繛鍫熺矒濮婅櫣娑甸崨顔俱€愬銈庡亝濞茬喖宕洪埀顒併亜閹哄棗浜鹃梺鎸庢穿婵″洤危閹版澘绫嶉柛顐g箘椤撴椽姊虹紒妯哄鐎殿噮鍓欒灃闁告侗鍠氶崢鎼佹⒑閸撴彃浜介柛瀣閹﹢鏁冮崒娑氬幈闁诲函缍嗛崑鍡樻櫠椤掑倻纾奸柛灞剧☉缁椦囨煙閻熸澘顏柟鐓庢贡閹叉挳宕熼棃娑欐珡闂傚倸鍊风粈渚€骞栭銈傚亾濮樺崬鍘寸€规洖缍婇弻鍡楊吋閸涱垽绱遍柣搴$畭閸庨亶藝娴兼潙纾跨€广儱顦伴悡鏇㈡煛閸ャ儱濡煎褜鍨伴湁闁绘ǹ绉鍫熺畳闂備焦瀵х换鍌毼涘Δ鍛厺闁哄洢鍨洪悡鍐喐濠婂牆绀堟慨妯挎硾閽冪喖鏌曟繛褍瀚烽崑銊╂⒑缂佹ê濮囨い鏇ㄥ弮閸┿垽寮撮姀鈥斥偓鐢告煥濠靛棗鈧懓鈻嶉崶銊d簻闊洦绋愰幉楣冩煛鐏炵偓绀嬬€规洟浜堕、姗€鎮㈡總澶夌处

    重磅专题
    往期文章
    最新文章