Vincent Jia 博客

          to be a better man, to be a bad man.

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            29 隨筆 :: 3 文章 :: 0 評論 :: 0 Trackbacks

          簡單討論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());

                  }

              }

          }

           from: http://www.cnblogs.com/fengye/archive/2007/02/18/652389.html

          posted on 2010-02-10 14:00 iLinux 閱讀(165) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 大新县| 商都县| 兴山县| 广昌县| 海晏县| 大姚县| 洛扎县| 宝兴县| 宜良县| 墨竹工卡县| 瑞安市| 江陵县| 阿拉善盟| 客服| 大庆市| 浦城县| 宜州市| 定襄县| 镇平县| 崇仁县| 炉霍县| 雷山县| 峨山| 佛学| 普兰县| 台州市| 黔西| 墨脱县| 高青县| 枣强县| 喀喇沁旗| 邮箱| 栾川县| 江北区| 五寨县| 兴海县| 来安县| 玉树县| 栾川县| 封开县| 手机|