小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

關(guān)于class.forname和contextClassloader

 燮羽 2010-11-06

自從java1.2開始,java的classloader有了階層體系。

這是我之前說過的,最初的例如rt.jar里面的class,比如Object是由c++寫的bootstrapclassloader來載入的。

bootstrapclassloader的孩子extclassloader搜索jre里面的用于存放java擴展jar的目錄負責載入其中的class。

然后是appclassloader或者叫做systemclassloader,是搜索CLASSPATH環(huán)境變量或者-cp參數(shù)里面指定的目錄和壓縮文件。

任何一個class的載入都需要一個classloader,而且一旦載入就無法改變,并且如果不加指定或者直接使用,都會默認使用caller的classloader來載入用到的class。

而1.2里面classloader階層迭代體系是,每次需要載入時,首先看父親能不能載入,也就是說是從根往下找的,在上層找到就不往下找了,這樣的機制能夠保證安全性。

class.forname為我們java提供了強大的靈活性,我們甚至在構(gòu)建系統(tǒng)時,即將運行的代碼不存在也沒有關(guān)系。

public class DynamicLoader
{
public static void main(String[] args)
throws Exception
{
Class toRun = Class.forName(args[0]);
String[] newArgs = scrubArgs(args);
Method mainMethod = findMain(toRun);
mainMethod.invoke(null, new Object[] { newArgs });
}
private static String[] scrubArgs(String[] args)
{
String[] toReturn = new String[args.length-1];
for (int i=1; i<args.length; i++)
{
toReturn[i-1] = args[i].toLowerCase();
}
return toReturn;
}
private static Method findMain(Class clazz)
throws Exception
{
Method[] methods = clazz.getMethods();
for (int i=0; i<methods.length; i++)
{
if (methods[i].getName().equals("main"))
return methods[i];
}
return null;
}
}

像這個程序,可以用來運行任何的java程序,例如我們寫了一個Echo:
public class Echo
{
public static void main (String args[])
{
for (int i=0; i<args.length; i++)
{
System.out.println("Echo arg"+i+" = "+args[i]);
}
}
}

我們可以
java DynamicLoader Echo ONE TWO THREE

輸出:
Echo arg0 = one
Echo arg1 = two
Echo arg2 = three

于是我們將DynamicLoader打包成jar,扔到ext目錄,再次運行:
java DynamicLoader Echo ONE TWO THREE
Exception in thread "main" java.lang.ClassNotFoundException: Echo
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:191)
at java.lang.ClassLoader.loadClass(ClassLoader.java:280)
at java.lang.ClassLoader.loadClass(ClassLoader.java:237)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:124)
at DynamicLoader.main(DynamicLoader.java:8)

怎么回事呢?
明明當前目錄下有Echo.class???

這就是階層迭代機制造成的,載入DynamicLoader的classloader是ext,用class.forname默認也會使用extclassloader,往上只有bootstrapclassloader,根本找不到了。

那怎么辦呢?

我們只有使用
Thread t = Thread.currentThread();
ClassLoader cl = t.getContextClassLoader();
Class toRun = cl.loadClass(args[0]);

contextClassLoader來做,或者我們直接指定是systemclassloader
Class.forName(args[0],
true,
ClassLoader.getSystemClassLoader());

這里用了三個參數(shù)的forName,只有用以上兩種辦法,改變載入class的classloader,才能找得到。

contextClassloader是和線程Thread掛鉤的,一個線程只有一個,并且可以設(shè)定安全機制,如果不加以改換,默認就是systemclassloader,而且這個線程創(chuàng)建出來的線程會保留創(chuàng)建者的classloader。

這些在容器實現(xiàn)和企業(yè)級服務(wù)器方面或者像jndi,rmi等技術(shù)上使用得非常多,光是tomcat最深的classloader是第七層,websphere就更不用說了。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多