熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

如何尋一個類X實例中類的物理所在?

2013-11-15 11:46:53  來源: JSP教程 

  問題: 當我擁有一個類X的實例我怎麼在運行的時候實時找出它的類的物理所在?
  在我給你答案之前我必須指出如果你堅持養成一個好習慣編程序時總是考慮與硬盤位置無關那麼你的java學習將會進展的很順利當你要裝載資源的時候比如一些屬性和配置文件盡可能的使用ResourceBundlegetBundle()而不是使用javautilFile除非真的是必須這樣這樣做不僅有利於你的JEE應用開發而且越到後來你就越會發現我怎麼有那麼多東西要裝載?這個時候你就會覺得這個方法確實給你帶來了方便
  
  盡管如此追尋到class的根源有時候在程序測試和debug的時候會很有用由於這個想法我給出了一種很有幫助的方法能夠替我們完成這個任務這些所有都是基於jse的api的
  /**
     * Given a Class object attempts to find its class location [returns null
     * if no such definition can be found] Use for testing/debugging only
     *
     * @return URL that points to the class definition [null if not found]
     */
    public static URL getClassLocation (final Class cls)
    {
      if (cls == null) throw new IllegalArgumentException (null input: cls);
      
      URL result = null;
      final String clsAsResource = clsgetName ()replace ( /ncat (class);
      
      final ProtectionDomain pd = clsgetProtectionDomain ();
      // javalangClass contract does not specify if pd can ever be null;
      // it is not the case for Suns implementations but guard against null
      // just in case:
      if (pd != null)
      {
        final CodeSource cs = pdgetCodeSource ();
        // cs can be null depending on the classloader behavior:
        if (cs != null) result = csgetLocation ();
        
        if (result != null)
        {
          // Convert a code source location into a full class file location
          // for some common cases:
          if (fileequals (resultgetProtocol ()))
          {
            try
            {
              if (resulttoExternalForm ()endsWith (jar) ||
                resulttoExternalForm ()endsWith (zip))
                result = new URL (jar:ncat (resulttoExternalForm ())
                 ncat(!/ncat (clsAsResource));
              else if (new File (resultgetFile ())isDirectory ())
                result = new URL (result clsAsResource);
            }
            catch (MalformedURLException ignore) {}
          }
        }
      }
      
      if (result == null)
      {
        // Try to find cls definition as a resource; this is not
        // document.d to be legal but Suns implementations seem to     //allow this:
        final ClassLoader clsLoader = clsgetClassLoader ();
        
        result = clsLoader != null ?
          clsLoadergetResource (clsAsResource) :
          ClassLoadergetSystemResource (clsAsResource);
      }
      
      return result;
    }
   
  你最好通過這個類的ProtectionDomain方法來獲得這個類的代碼文件來源以及url地址然而有一個問題就是 ClassgetProtectionDomain()似乎並不會返回一個null值在api裡也似乎是這麼說的 但是ClassgetProtectionDomain()並不一定就會返回一個有效的url值所以我們在後面通過判斷result來得知是否有效
  
  所有的細節都是classloader的動作我們知道classloader就是裝載和定義我們的class的通過javalangClassLoaderdefineClass()—個參數而且ProtectionDomain參數不能為空我們可以建立需要的類以及相關受保護的區域
  
  一般來講 URLClassLoader以及相關的擴展一般都會遵循這個規則但是並非所有自定義的classloader都會保證自動實現它
  
  如果第一步失敗了你可以試試通過getResource()來獲得class結尾的文件的位置Java規范裡面並沒有詳細說明這樣作是否允許:因為任何代碼都能通過URLS讀取整個類的定義是一個潛在的安全漏洞有一些jvm已經禁止通過getResource()來裝載class文件然而sun的jdk卻是通過這個途徑來裝載類的這似乎傳遞了某些合法的信息
  
  最後千萬不要忘記不要去尋找任何不存在的東西一個javalangClass類是不需要真正存在一個class文件的一個明顯的例子就是動態代理類:它的字節碼定義是在運行的時候合成的 對於它getClassLocation()將會返回null 將來jee裡面將更多的依靠這種運行時構造的方法因為這些原因還有就是虛擬機各自都不同我提供的這種方法你最好只是用來做測試和debug
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19616.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.