服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

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());

        }

    }

}

扫描关注微信公众号