熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

JVM技術,反射與動態代理

2022-06-13   來源: Java核心技術 

  Java程序的工作機制Java對象都以單獨的class文件存在java虛擬機將其載入並執行其虛擬機指令

   

  Java虛擬機查找這些java對象

  java虛擬機根據class path來查找java對象而虛擬機的class path又分為三層

  bootstrapsunbootclasspath

  extension: javaextdirs

  application: javaclasspath

  三個class path各有對應的classloader由上而下形成父子關系

  當程序中調用new指令或者ClassLoaderload方法時其順序如下

         首先查看application的classloader中是否已有對應的class緩存如果有則返回並根據class分配內存如果沒有接下一步

         首先查看extension的classloader中是否已有對應的class緩存如果有則返回並根據class分配內存如果沒有接下一步

         首先查看bootstrap的classloader中是否已有對應的class緩存如果有則返回並根據class分配內存如果沒有接下一步

         由bootstrap的classloader在其class path中試圖加載該class如果有則將該class放入cache中並返回如果沒有接下一步

         由extension的classloader在其class path中試圖加載該class如果有則將該class放入cache中並返回如果沒有接下一步

         由application的classloader在其class path中試圖加載該class如果有則將該class放入cache中並返回如果沒有則拋出ClassNotFound的exception

   

  Java虛擬機加載這些java對象

  每個java虛擬機都在其啟動時產生一個唯一的class heap並把所有的class instance都分配在其中其中每個類實例的信息又分兩部分fields域和methods域每個類實例各自擁有fields但同一個類的不同實例共享methods

   

  反射

  JVM對反射的處理

  簡單例子代碼

  import javalangreflectInvocationHandler;

  import javalangreflectMethod;

  import javalangreflectInvocationTargetException;

  import javaioIOException;

   

  public class Main {

  public static void main(String[] args){

  TempImpl t = new TempImpl(temp);

  try {

  Method tTalk = tgetClass()getMethod(Talk new Class[]) ;

  tTalkinvoke(t null);

  } catch (NoSuchMethodException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  } catch (IllegalAccessException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  } catch (InvocationTargetException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  }

  try {

  Systeminread();

  } catch (IOException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  }

  }

  }

  復雜例子代碼

  import javalangreflectInvocationHandler;

  import javalangreflectMethod;

  import javalangreflectInvocationTargetException;

  import javaioIOException;

   

  public class Main {

  public static void main(String[] args){

  TempImpl t = new TempImpl(temp);

  TempImpl t = new TempImpl(temp);

  Temp temp = new Temp();

  try {

  Method tTalk = tgetClass()getMethod(Talk new Class[]) ;

  Method tTalk = tgetClass()getMethod(Talk new Class[]) ;

  tTalkinvoke(t null);

  tTalkinvoke(t null);

  if(tTalkequals(tTalk)){

  Systemoutprintln(equals);

  }

  else{

  Systemoutprintln(not equals);

  }

  if(tTalk==tTalk){

  Systemoutprintln(ref equals);

  }

  else{

  Systemoutprintln(ref not equals);

  }

  tTalkinvoke(temp null);

  } catch (NoSuchMethodException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  } catch (IllegalAccessException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  } catch (InvocationTargetException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  }

  try {

  Systeminread();

  } catch (IOException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  }

  }

  }

   

  分析java虛擬機把每個methods當作一個執行單元該執行單元帶有兩種簽名類簽名和屬性簽名(publicstatic等) 反射的第一步驗證簽名的合法性驗證通過後順序執行該method中的指令當需要訪問類實例的fields和傳入參數時由虛擬機注入

   

  動態代理

  Sun對動態代理的說明

  一個簡單例子代碼

  動態代理的內部實現——代碼生成

  研究JDK源代碼發現在Proxy的sun實現中調用了sunmiscProxyGenerator類的generateProxyClass( proxyName interfaces)方法其返回值為byte[]和class文件的內存類型一致於是做如下試驗


  public class  ProxyClassFile{

  public static void main(String[] args){

  String proxyName = TempProxy;

  TempImpl t = new TempImpl(proxy);

  Class[] interfaces =tgetClass()getInterfaces();

  

  byte[] proxyClassFile = ProxyGeneratorgenerateProxyClass(

  proxyName interfaces);

  File f = new File(classes/TempProxyclass);

  try {

  FileOutputStream fos = new FileOutputStream(f);

  foswrite(proxyClassFile);

  fosflush();

  fosclose();

  } catch (FileNotFoundException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  } catch (IOException e) {

  eprintStackTrace();  //To change body of catch statement use File | Settings | File Templates

  }

  }

  }

  運行該類到class文件夾下利用反編譯技術發現原來其采用了代碼生產技術

   

  public interface Temp{

  public void Talk();

  public void Run();

  }

  import javalangreflect*;

   

  public final class TempProxy extends Proxy

  implements Temp{

   

  private static Method m;

  private static Method m;

  private static Method m;

  private static Method m;

  private static Method m;

   

  public TempProxy(InvocationHandler invocationhandler)   {

  super(invocationhandler);

  }

   

  public final void Run()    {

  try {

  hinvoke(this m null);

  return;

  }

  catch(Error _ex) { }

  catch(Throwable throwable)  {

  throw new UndeclaredThrowableException(throwable);

  }

  }

   

  public final String toString(){

  try{

  return (String)hinvoke(this m null);

  }

  catch(Error _ex) { }

  catch(Throwable throwable)  {

  throw new UndeclaredThrowableException(throwable);

  }

  return ;

  }

   

  public final int hashCode() {

  try {

  return ((Integer)hinvoke(this m null))intValue();

  }

  catch(Error _ex) { }

  catch(Throwable throwable){

  throw new UndeclaredThrowableException(throwable);

  }

  return ;

  }

   

  public final void Talk(){

  try{

  hinvoke(this m null);

  return;

  }

  catch(Error _ex) { }

  catch(Throwable throwable) {

  throw new UndeclaredThrowableException(throwable);

  }

  }

   

  public final boolean equals(Object obj) {

  try  {

  return ((Boolean)hinvoke(this m new Object[] {

  obj

  }))booleanValue();

  }

  catch(Error _ex) { }

  catch(Throwable throwable) {

  throw new UndeclaredThrowableException(throwable);

  }

  return false;

  }

   

  static{

  try{

  m = ClassforName(Temp)getMethod(Run new Class[]);

  m = ClassforName(javalangObject)getMethod(toString new Class[]);

  m = ClassforName(javalangObject)getMethod(hashCode new Class[]);

  m = ClassforName(Temp)getMethod(Talk new Class[]);

  m = ClassforName(javalangObject)getMethod(equals new Class[] {

  ClassforName(javalangObject)

  });

  }

  catch(NoSuchMethodException nosuchmethodexception) {

  throw new NoSuchMethodError(nosuchmethodexceptiongetMessage());

  }

  catch(ClassNotFoundException classnotfoundexception) {

  throw new NoClassDefFoundError(classnotfoundexceptiongetMessage());

  }

  }

  }


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25693.html
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.