乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

       燮羽 2010-11-06

      自從java1.2開(kāi)始,java的classloader有了階層體系。

      這是我之前說(shuō)過(guò)的,最初的例如rt.jar里面的class,比如Object是由c++寫(xiě)的bootstrapclassloader來(lái)載入的。

      bootstrapclassloader的孩子extclassloader搜索jre里面的用于存放java擴(kuò)展jar的目錄負(fù)責(zé)載入其中的class。

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

      任何一個(gè)class的載入都需要一個(gè)classloader,而且一旦載入就無(wú)法改變,并且如果不加指定或者直接使用,都會(huì)默認(rèn)使用caller的classloader來(lái)載入用到的class。

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

      class.forname為我們java提供了強(qiáng)大的靈活性,我們甚至在構(gòu)建系統(tǒng)時(shí),即將運(yùn)行的代碼不存在也沒(méi)有關(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;
      }
      }

      像這個(gè)程序,可以用來(lái)運(yùn)行任何的java程序,例如我們寫(xiě)了一個(gè)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目錄,再次運(yùn)行:
      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)

      怎么回事呢?
      明明當(dāng)前目錄下有Echo.class???

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

      那怎么辦呢?

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

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

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

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

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

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

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多