Vincent Jia 博客

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

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            29 隨筆 :: 3 文章 :: 0 評(píng)論 :: 0 Trackbacks

          簡(jiǎn)單討論JVM的class加載機(jī)制,給出兩個(gè)反射的例子代碼并分析工作原理,并給出了sun的動(dòng)態(tài)代理實(shí)現(xiàn)原理——代碼生成

          JavaVM,反射與動(dòng)態(tài)代理

           

          Java程序的工作機(jī)制:Java對(duì)象都以單獨(dú)的class文件存在,java虛擬機(jī)將其載入并執(zhí)行其虛擬機(jī)指令。

           

          Java虛擬機(jī)查找這些java對(duì)象:

          java虛擬機(jī)根據(jù)class path來(lái)查找java對(duì)象,而虛擬機(jī)的class path又分為三層:

          bootstrapsun.boot.class.path

          extension: java.ext.dirs

          application: java.class.path

          三個(gè)class path各有對(duì)應(yīng)的classloader。由上而下形成父子關(guān)系

          當(dāng)程序中調(diào)用new指令,或者ClassLoader.load方法時(shí)。其順序如下:

          1.       首先查看applicationclassloader中是否已有對(duì)應(yīng)的class緩存,如果有則返回,并根據(jù)class分配內(nèi)存。如果沒(méi)有,接下一步。

          2.       首先查看extensionclassloader中是否已有對(duì)應(yīng)的class緩存,如果有則返回,并根據(jù)class分配內(nèi)存。如果沒(méi)有,接下一步。

          3.       首先查看bootstrapclassloader中是否已有對(duì)應(yīng)的class緩存,如果有則返回,并根據(jù)class分配內(nèi)存。如果沒(méi)有,接下一步。

          4.       bootstrapclassloader在其class path中試圖加載該class,如果有,則將該class放入cache中,并返回。如果沒(méi)有,接下一步。

          5.       extensionclassloader在其class path中試圖加載該class,如果有,則將該class放入cache中,并返回。如果沒(méi)有,接下一步。

          6.       applicationclassloader在其class path中試圖加載該class,如果有,則將該class放入cache中,并返回。如果沒(méi)有,則拋出ClassNotFoundexception

           

          Java虛擬機(jī)加載這些java對(duì)象:

          每個(gè)java虛擬機(jī)都在其啟動(dòng)時(shí)產(chǎn)生一個(gè)唯一的class heap,并把所有的class instance都分配在其中。其中每個(gè)類(lèi)實(shí)例的信息又分兩部分,fields域和methods域。每個(gè)類(lèi)實(shí)例各自擁有fields,但同一個(gè)類(lèi)的不同實(shí)例共享methods

           

          反射

          JVM對(duì)反射的處理

          簡(jiǎn)單例子代碼:

          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.

                  }

              }

          }

          復(fù)雜例子代碼:

          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虛擬機(jī)把每個(gè)methods當(dāng)作一個(gè)執(zhí)行單元。該執(zhí)行單元帶有兩種簽名:類(lèi)簽名和屬性簽名(publicstatic等)。 反射的第一步,驗(yàn)證簽名的合法性。驗(yàn)證通過(guò)后,順序執(zhí)行該method中的指令,當(dāng)需要訪問(wèn)類(lèi)實(shí)例的fields和傳入?yún)?shù)時(shí),由虛擬機(jī)注入。

           

          動(dòng)態(tài)代理

          Sun對(duì)動(dòng)態(tài)代理的說(shuō)明:

          一個(gè)簡(jiǎn)單例子代碼:

          動(dòng)態(tài)代理的內(nèi)部實(shí)現(xiàn)——代碼生成:

          研究JDK源代碼,發(fā)現(xiàn)在Proxysun實(shí)現(xiàn)中調(diào)用了sun.misc.ProxyGenerator類(lèi)的generateProxyClass( proxyName, interfaces)方法,其返回值為byte[]class文件的內(nèi)存類(lèi)型一致。于是做如下試驗(yàn):

          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.

                  }

                 }

          }

          運(yùn)行該類(lèi),到class文件夾下,利用反編譯技術(shù),發(fā)現(xiàn)原來(lái)其采用了代碼生產(chǎn)技術(shù):

           

          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 閱讀(169) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 博爱县| 虹口区| 威远县| 高台县| 南康市| 平远县| 东莞市| 谢通门县| 梨树县| 四平市| 梁平县| 富宁县| 罗江县| 奈曼旗| 长宁区| 新河县| 孟村| 水城县| 阳谷县| 临清市| 页游| 鄂伦春自治旗| 如东县| 丰宁| 济阳县| 吴堡县| 巢湖市| 松桃| 襄城县| 德令哈市| 星子县| 崇信县| 大名县| 富裕县| 贡觉县| 江孜县| 田阳县| 抚顺市| 绍兴县| 永定县| 监利县|