千里冰封
          JAVA 濃香四溢
          posts - 151,comments - 2801,trackbacks - 0
          前幾天我寫了一個類的加載機制,也就是有關類的加載順序問題,這一次我們將了解一下如何利用自定義的類加載器實現類的隱藏,然后再運行的時候動態的讀出被隱藏的類.這樣就可以在一定的程度上保護我們的類了,我們還是先看看代碼吧.

          我們先寫一個URLClassLoader的子類,這樣我們就可以用定義在其中的一些protected方法了.

           

          /*
           * Test6.java
           *
           * Created on 2007-9-24, 10:57:57
           *
           * To change this template, choose Tools | Templates
           * and open the template in the editor.
           
          */

          package test1;

          import java.io.DataInputStream;
          import java.io.DataOutputStream;
          import java.io.FileInputStream;
          import java.io.FileOutputStream;
          import java.io.IOException;
          import java.io.InputStream;
          import java.lang.reflect.Method;
          import java.net.URL;
          import java.net.URLClassLoader;
          import java.util.logging.Level;
          import java.util.logging.Logger;

          /**
           *
           * 
          @author hadeslee
           
          */
          @SuppressWarnings(value 
          = "unchecked")
          public class Test6 extends URLClassLoader {

              
          public Test6() {
                  
          super(new URL[0]);
                  Thread.currentThread().setContextClassLoader(
          this);
                  ClassLoader cl 
          = this.getClass().getClassLoader();
                  
          if (cl instanceof URLClassLoader) {
                      URLClassLoader loader 
          = (URLClassLoader) cl;
                      URL[] urls 
          = loader.getURLs();
                      
          for (URL u : urls) {
                          System.out.println(u);
                          
          this.addURL(u);
                      }
                  }
              }

              
          //根據類的全限定名得到類的字節數組
              private byte[] getClassData(String name) {
                  
          try {
                      InputStream is 
          = this.getClass().getResourceAsStream(getPathName(name));
                      
          byte[] temp = new byte[is.available()];
                      is.read(temp);
                      is.close();
                      
          return temp;
                  } 
          catch (IOException ex) {
                      Logger.getLogger(Test6.
          class.getName()).log(Level.SEVERE, null, ex);
                      
          return null;
                  }
              }

              
          //要隱藏的類
              private void hideClasses(String className) {
                  DataOutputStream dout 
          = null;
                  
          try {
                      dout 
          = new DataOutputStream(new FileOutputStream("hide.dat"));
                      
          for (String s : className) {
                          dout.writeUTF(s);
                          
          byte[] data = this.getClassData(s);
                          dout.writeInt(data.length);
                          dout.write(data);
                      }
                  } 
          catch (IOException ex) {
                      Logger.getLogger(Test6.
          class.getName()).log(Level.SEVERE, null, ex);
                  } 
          finally {
                      
          try {
                          dout.close();
                      } 
          catch (IOException ex) {
                          Logger.getLogger(Test6.
          class.getName()).log(Level.SEVERE, null, ex);
                      }
                  }
              }
              
          private Class findClass0(String className){
                  DataInputStream din 
          = null;
                  
          try {
                      din 
          = new DataInputStream(new FileInputStream("hide.dat"));
                      
          while (true) {
                          String name 
          = din.readUTF();
                          System.out.println(
          "find name=" + name);
                          
          int length = din.readInt();
                          
          byte[] data = new byte[length];
                          din.read(data);
                          
          if (name.equals(className)) {
                              
          return this.defineClass(name, data, 0, length);
                          }
                      }
                  } 
          catch (IOException ex) {
                      Logger.getLogger(Test6.
          class.getName()).log(Level.SEVERE, null, ex);
                  } 
          catch (ClassFormatError classFormatError) {
                  } 
          finally {
                      
          try {
                          
          if (din != null) {
                              din.close();
                          }
                      } 
          catch (Exception exe) {
                          exe.printStackTrace();
                      }
                  }
                  
          return null;
              }
              
          protected Class findClass(String className) throws ClassNotFoundException {
                  Class c
          =this.findClass0(className);
                  
          if(c==null){
                      
          return super.findClass(className);
                  }
          else{
                      
          return c;
                  }
              }

              
          //根據類名得到完整的加載路徑名
              private String getPathName(String name) {
                  StringBuilder sb 
          = new StringBuilder();
                  String[] names 
          = name.split("\\.");
                  
          for (String s : names) {
                      sb.append(
          "/").append(s);
                  }
                  sb.append(
          ".class");
                  
          return sb.toString();
              }

              
          public static void main(String[] args) throws Exception {
                  Test6 t 
          = new Test6();
                  t.hideClasses(
          "test2.A""test2.B");
                  Class c 
          = t.findClass("test2.B");
                  Object o 
          = c.newInstance();
                  test2.B b
          =(test2.B)o;
                  Method m 
          = c.getDeclaredMethod("print", String.class);
                  m.invoke(o, 
          "我是中國人");
                  System.out.println(c);
              }
          }

           

          以下是A和B類的代碼

          /*
           * A.java
           * 
           * Created on 2007-9-24, 10:26:47
           * 
           * To change this template, choose Tools | Templates
           * and open the template in the editor.
           
          */

          package test2;

          /**
           *
           * 
          @author hadeslee
           
          */
          public class A {
              
          private int index=10;
              
          public void doSth(){
                  
              }
          }

          /*
           * B.java
           * 
           * Created on 2007-9-24, 10:29:04
           * 
           * To change this template, choose Tools | Templates
           * and open the template in the editor.
           
          */

          package test2;

          /**
           *
           * 
          @author hadeslee
           
          */
          public class B extends A{
              
          public void print(String s){
                  System.out.println(s);
              }
          }

          此程序的實現思路是:先寫一個繼承自URLClassLoader的類加載器,然后我們要類的時候,就從這個類加載器去加載,我們要隱藏類的時候,也是由這個類加載器去實現隱藏, 其實隱藏就是把很多類放到一個文件里面去,然后加上自己的IO寫法,然后在需要的時候,又可以又自己寫進去的方法,把類的字節數組讀出來,把它還原成一個類.在這里我們還需要重寫一個方法,那就是定義在ClassLoader里面的findClass(String name)的方法,讓它在找類的時候,不要亂找,而是用我們自己的方法來找,當我們自己的方法找不到的時候,才由它來找,這樣的話,就可以實現先找我們自己的方式隱藏的類,再找一般情況下面的類.

          對于類的加載,有很多東西是可以研究和學習的,希望在以后的學習過程中,能夠慢慢了解它.


          盡管千里冰封
          依然擁有晴空

          你我共同品味JAVA的濃香.
          posted on 2007-09-24 11:04 千里冰封 閱讀(965) 評論(3)  編輯  收藏 所屬分類: JAVASE

          FeedBack:
          # re: 類加載機制實現類的隱藏
          2007-09-24 12:39 | 狂放不羈
          不錯。哈哈。偶也在學習這個。  回復  更多評論
            
          # re: 類加載機制實現類的隱藏
          2007-09-24 12:54 | 千里冰封
          你也來blogjava?  回復  更多評論
            
          # re: 類加載機制實現類的隱藏
          2007-09-26 16:40 | 狂放不羈
          對。blogjava里面有很多高手寫的東西。看看挺不錯的哈哈。  回復  更多評論
            
          主站蜘蛛池模板: 梅州市| 横峰县| 林芝县| 黑山县| 阿城市| 庆云县| 确山县| 霍州市| 香格里拉县| 扎兰屯市| 陆河县| 凤城市| 开封县| 郧西县| 绵竹市| 文山县| 小金县| 台山市| 永善县| 九龙坡区| 宁明县| 潜江市| 延吉市| 郎溪县| 长治县| 台中县| 壤塘县| 石楼县| 嘉祥县| 渭南市| 新巴尔虎右旗| 峡江县| 顺平县| 平昌县| 乌兰浩特市| 五指山市| 安塞县| 灵石县| 资溪县| 东乡县| 长垣县|