問題: 當我擁有一個類X的實例我怎麼在運行的時候實時找出它的類的物理所在? 在我給你答案之前
我必須指出
如果你堅持養成一個好習慣
編程序時總是考慮與硬盤位置無關
那麼你的java學習將會進展的很順利
當你要裝載資源的時候
比如一些屬性和配置文件
盡可能的使用ResourceBundle
getBundle()而不是使用java
util
File
除非真的是必須這樣
這樣做不僅有利於你的J
EE應用開發
而且越到後來
你就越會發現
我怎麼有那麼多東西要裝載?這個時候
你就會覺得這個方法確實給你帶來了方便
盡管如此
追尋到class的根源有時候在程序測試和debug的時候會很有用
由於這個想法
我給出了一種很有幫助的方法能夠替我們完成這個任務
這些所有都是基於j
se的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 = cls
getName ()
replace (
/
ncat (
class
);
final ProtectionDomain pd = cls
getProtectionDomain ();
// java
lang
Class contract does not specify if
pd
can ever be null;
// it is not the case for Sun
s implementations
but guard against null
// just in case:
if (pd != null)
{
final CodeSource cs = pd
getCodeSource ();
//
cs
can be null depending on the classloader behavior:
if (cs != null) result = cs
getLocation ();
if (result != null)
{
// Convert a code source location into a full class file location
// for some common cases:
if (
file
equals (result
getProtocol ()))
{
try
{
if (result
toExternalForm ()
endsWith (
jar
) ||
result
toExternalForm ()
endsWith (
zip
))
result = new URL (
jar:ncat (result
toExternalForm ())
ncat(
!/
ncat (clsAsResource));
else if (new File (result
getFile ())
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 Sun
s implementations seem to //allow this:
final ClassLoader clsLoader = cls
getClassLoader ();
result = clsLoader != null ?
clsLoader
getResource (clsAsResource) :
ClassLoader
getSystemResource (clsAsResource);
}
return result;
}
你最好通過這個類的ProtectionDomain方法來獲得這個類的代碼文件來源以及url地址
然而
有一個問題就是
Class
getProtectionDomain()似乎並不會返回一個null值
在api裡也似乎是這麼說的
但是Class
getProtectionDomain()並不一定就會返回一個有效的url值
所以我們在後面通過判斷result來得知是否有效
所有的細節都是classloader的動作
我們知道
classloader就是裝載和定義我們的class的
通過java
lang
ClassLoader
defineClass()—
個參數
而且ProtectionDomain參數不能為空
我們可以建立需要的類以及相關受保護的區域
一般來講
URLClassLoader以及相關的擴展一般都會遵循這個規則
但是並非所有自定義的classloader都會保證自動實現它
如果第一步失敗了
你可以試試通過getResource()來獲得
class結尾的文件的位置
Java規范裡面並沒有詳細說明這樣作是否允許:因為
任何代碼都能通過URLS讀取整個類的定義
是一個潛在的安全漏洞
有一些jvm已經禁止通過getResource()來裝載
class文件
然而
sun的jdk卻是通過這個途徑來裝載類的
這似乎傳遞了某些合法的信息
最後
千萬不要忘記
不要去尋找任何不存在的東西
一個java
lang
Class類是不需要真正存在一個
class文件的
一個明顯的例子就是動態代理類:它的字節碼定義是在運行的時候合成的
對於它
getClassLocation()將會返回null
將來
j
ee裡面將更多的依靠這種運行時構造的方法
因為這些原因
還有就是虛擬機各自都不同
我提供的這種方法你最好只是用來做測試和debug
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19616.html