zoukankan      html  css  js  c++  java
  • JVM,反射与动态代理

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

    JavaVM,反射与动态代理

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

            }

        }

    }

     

  • 相关阅读:
    python学习笔记——拾
    python学习笔记——玖
    Python 实现栈与队列
    Vijos1774 机器翻译 [模拟]
    Vijos1788 第K大 [模拟]
    Python 序列求和
    HDU 2102 A计划 DFS与BFS两种写法 [搜索]
    Python 多组输入
    Python 文件读写
    HDU 2068 RPG错排 [错排公式]
  • 原文地址:https://www.cnblogs.com/fengye/p/652389.html
Copyright © 2011-2022 走看看