<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 78, comments - 34, trackbacks - 0, articles - 1
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    2009-12-09休息 JAVA類加載器

    Posted on 2009-12-10 01:09 長城 閱讀(249) 評論(0)  編輯  收藏

                    從張老師的基礎增強課上,我就想深入了解一下類加載器。然后聽懂了張老師的課,知道了JAVA類加載的方式,以及實現自己的類加載器的應用。但一直沒有自己去編寫類加載器,也對class文件的具體處理方式不了解。今日休息,有時間深入了解一下。

     

    一、JAVA有三個類加載器:

    1.bootstrap class loader,負責加載系統類,比如jdkrt.jar包里的類。

    2.extension class loader,負責加載jre/lib/ext目錄下的所有類。

    3.system class loader,負責加載環境變量classpath指向目錄下的所有類。

     

    他們三個依次是“父子關系”,因為bootstrap class loader一般是使用C語言編寫的,所以用戶無法獲取它的對象。

     

    當在classpath環境變量中的一個class文件被加載時,system class loader會將class交給父類extension class loader加載,extension class loader會將class交給bootstrap class loader加載。如果bootstrap class loader加載不了,則返回給extension class loader加載,如果extension class loader加載不了,則返回給system class loader加載。

     

    被其中一個加載器成功加載后,便解析class文件。如果class文件中有使用到其他類對象,則繼續調用類加載器加載。

     

    有些情況下不希望被用戶看到Class文件的明文,比如為了保護軟件的安全、防止破解等?!?/span>JAVA核心技術第2卷》也有提到編寫自己的類加載器,實現加載被加了密的class文件。

     

    下面實現一個自己的類加載器,加載被加密了的class文件:

     

    EasyTest.java用于被自定義類加載器加載。

    public class EasyTest {

          public void print(){

                System.out.println("EasyTest,you did it!");

          }

    }

     

    Mycipher.java用于加密EasyTest.class。

    package cn.itcast.cc.cipher;

     

    import java.io.*;

    import java.security.Key;

    import javax.crypto.*;

     

    public class MyCipher {

          private Key key = null;

          private String traninfo = null;

     

          public MyCipher(Key key, String traninfo) {

                this.key = key;

                this.traninfo = traninfo;

          }

     

          public void cipher(InputStream ins, OutputStream ous) throws IOException {

                // 創建加密輸出流

                Cipher cip = null;

                CipherOutputStream cos = null;

                try {

                      cip = Cipher.getInstance(this.traninfo);

                      cip.init(Cipher.ENCRYPT_MODE, this.key);

                      cos = new CipherOutputStream(ous, cip);

                      // 寫出到輸入流

                      int len = 0;

                      byte[] buf = new byte[1024];

                      while ((len = ins.read(buf)) != -1) {

                            cos.write(buf, 0, len);

                      }

                } catch (Exception e) {

                      e.printStackTrace();

                } finally {

                      // 釋放輸入和輸出流

                      cos.close();

                      ins.close();

                      ous.close();

                }

          }

    }

     

    MyClassLoader.java是自定義類加載器,用于解密被加密后的class文件。

    package cn.itcast.cc.classloader;

     

    import java.io.*;

    import java.security.Key;

    import javax.crypto.*;

     

    public class MyClassLoader extends ClassLoader {

          private Key key = null;

          private String traninfo = null;

     

          public MyClassLoader(Key key, String traninfo) {

                this.key = key;

                this.traninfo = traninfo;

          }

     

          @Override

          @SuppressWarnings("unchecked")

          protected Class findClass(String name) throws ClassNotFoundException {

                // 獲取class解密后的字節碼

                byte[] classBytes = null;

                try {

                      classBytes = loadClassBytes(name);

                } catch (Exception e) {

                      throw new ClassNotFoundException(name);

                }

               

                // 使用字節碼,實例類對象

                String clname = name.substring(name.lastIndexOf("/") + 1, name

                            .lastIndexOf("."));

                Class cl = defineClass(clname, classBytes, 0, classBytes.length);

                if (cl == null)

                      throw new ClassNotFoundException(name);

                return cl;

          }

     

          private byte[] loadClassBytes(String name) throws IOException {

                // 讀入文件

                FileInputStream ins = null;

                ByteArrayOutputStream baos = null;

                CipherInputStream cis = null;

                byte[] result = null;

                try {

                      ins = new FileInputStream(name);

                      Cipher cip = Cipher.getInstance(this.traninfo);

                      cip.init(Cipher.DECRYPT_MODE, this.key);

                      // 使用密碼解密class文件

                      cis = new CipherInputStream(ins, cip);

                      baos = new ByteArrayOutputStream();

                      int len = 0;

                      byte[] buf = new byte[1024];

                      while ((len = cis.read(buf)) != -1) {

                            baos.write(buf, 0, len);

                      }

                      result = baos.toByteArray();

                } catch (Exception e) {

                      e.printStackTrace();

                } finally {

                      // 釋放流

                      baos.close();

                      cis.close();

                      ins.close();

                }

     

                return result;

          }

    }

     

    Test.java,用于測試自定義類加載器。

    package cn.itcast.cc.testcalss;

     

    import java.io.*;

    import java.lang.reflect.Method;

    import java.security.Key;

    import javax.crypto.KeyGenerator;

    import cn.itcast.cc.cipher.MyCipher;

    import cn.itcast.cc.classloader.MyClassLoader;

     

    public class Test {

          public static void main(String[] args) {

                KeyGenerator keyGen;

                try {

                      // 創建密鑰

                      keyGen = KeyGenerator.getInstance("AES");

                      keyGen.init(128);

                      Key key = keyGen.generateKey();

                      keyGen = null;

     

                      MyCipher mc = new MyCipher(key,"AES/ECB/PKCS5Padding");

                      mc.cipher(new FileInputStream(new File("C:/EasyTestbak.class")),

                                  new FileOutputStream(new File("C:/EasyTest.class")));

     

                      MyClassLoader mcl = new MyClassLoader(key,"AES/ECB/PKCS5Padding");

                     

                      Class clazz = mcl.loadClass("C:/EasyTest.class");

                      Method meth = clazz.getMethod("print", null);

                      meth.invoke(clazz.newInstance(), null);

     

                } catch (Exception e1) {

                      e1.printStackTrace();

                }

          }

    }

     

    注意:將EasyTest.java編譯后放到C盤:C:/EasyTestbak.class

     

    例子寫的不干凈,主要是為了演示自定義類加載器!

     

                學習了tomcat servlet以來便對它們的實現機制比較感興趣,雖然已經弄懂了他們簡單的實現原理。但今日看到《實現自己的類加載器》這篇文章時,讓對有了更深入的了解。在tomcatwebapps目錄下的所有WEB應用中的class文件和jar文件,都是在Tomcat啟動時將全路徑記錄到URLClassloader中。需要什么類,直接調用URLClassloader.loaderclass()方法即可!

     

                我原本想自己找到class文件的全路徑,然后調用class.forname的方法不也可以嗎?但如果有JAR包,我還需要使用JARInputstream讀入,然后再搜索嗎?這樣太麻煩,所以還是使用URLClassloader比較好,它全處理了。

     

                它的實現原理,請看《實現自己的類加載器》 http://ajava.org/course/java/14990.html。

     

     

    參考文獻:《實現自己的類加載器》 http://ajava.org/course/java/14990.html


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 国产精品亚洲AV三区| 美女被免费网站91色| 亚洲一区二区三区无码影院| JLZZJLZZ亚洲乱熟无码| 日韩插啊免费视频在线观看| 亚洲日韩精品无码专区加勒比| 国产啪亚洲国产精品无码| 日日摸夜夜添夜夜免费视频| 亚洲s色大片在线观看| 免费无码又爽又刺激毛片| 免费播放在线日本感人片| 国产亚洲A∨片在线观看| 我要看免费的毛片| 99精品视频在线观看免费| 中文字幕乱码亚洲无线三区 | 国产日产成人免费视频在线观看| jizz在线免费观看| 亚洲色欲色欲www在线播放| 亚洲va中文字幕无码久久不卡| 国产精品美女午夜爽爽爽免费| 9久热精品免费观看视频| 亚洲一久久久久久久久| 亚洲Aⅴ无码专区在线观看q | 亚洲第一成人在线| 成人永久福利免费观看| 97av免费视频| a级毛片免费观看网站| 亚洲女女女同性video| 亚洲男女一区二区三区| 日本红怡院亚洲红怡院最新| 国产男女猛烈无遮挡免费视频网站| 久久99精品视免费看| GOGOGO免费观看国语| 猫咪免费人成在线网站 | a级毛片高清免费视频就| 免费无码国产在线观国内自拍中文字幕 | 日韩av无码久久精品免费| 成人免费av一区二区三区| 免费看一级高潮毛片| 亚洲最大天堂无码精品区| 亚洲国产精品成人综合久久久 |