2010-02-17 105 views
1

我想實現自定義類加載器,以便對我的jar文件進行數字簽名。 由於性能問題,我不想加密所有的類。 所以我想要實現一個自定義的類加載器,當它被稱爲 它將類委託給它的父類,如果父類未能加載它自己處理的類。 這是我的代碼:自定義類加載器的問題

package org.dpdouran.attach; 
import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.security.InvalidAlgorithmParameterException;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.security.spec.AlgorithmParameterSpec;import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 

public class CustomClassLoader extends ClassLoader { 
    private static final int BUFFER_SIZE = 8192; 
    @Override 
    protected Class<?> findClass(String className) throws ClassNotFoundException { 
     System.out.println("loading... "+className); 
     String clsFile = className.replace('.', '/') + ".class"; 
     InputStream in = getResourceAsStream(clsFile); 
     if(in==null) 
      return null; 
     byte[] buffer = new byte[BUFFER_SIZE]; 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     int n = -1; 
     try { 
      while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) { 
       out.write(buffer, 0, n); 
      } 
     } catch (IOException e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
     //do decrypt 
     byte[] classBytes = out.toByteArray(); 
     byte[] iv = new byte[] { (byte) 0x8E, 0x12, 0x39, (byte) 0x9C, 
       0x07, 0x72, 0x6F, 0x5A }; 
     AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv); 
     Cipher dcipher=null; 
     try { 
      dcipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 
     } catch (NoSuchAlgorithmException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     byte keyBytes[] = "abcdEFGH".getBytes(); 
     SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "DES"); 
     try { 
      dcipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec); 
     } catch (InvalidKeyException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidAlgorithmParameterException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     byte[] dbytes = null; 
     try { 
      dbytes = dcipher.doFinal(classBytes); 
     } catch (IllegalBlockSizeException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return defineClass(className, dbytes, 0, dbytes.length); 
    } 
    public CustomClassLoader(ClassLoader parent){ 
     super(sun.misc.Launcher.getLauncher().getClassLoader()); 
    } 
} 

還我已經改變默認的系統類加載器通過改變「java.system.class.loader」屬性。 當我運行我的應用程序時,它可以正常使用未加密的類,但是當它到達加密類時,它會拋出ClassFormatError,我的findClasses方法永遠不會被調用! 我怎麼能確定我的自定義類加載器將被加密類別調用? 感謝

回答

0

嘗試設置類加載器編程,看看它是否工作

Thread.currentThread().setContextClassLoader(myClassLoader); 

當我實現我的類加載器我實現了loadClass方法代替的findClass。嘗試做類似

try { 
    return super.loadClass(name); 
catch (Exception e) { 
    ... your code here 
} 

另一方面,文檔說不覆蓋loadClass但findClass。

//編輯

另一種想法。

它看起來像你保持你的加密類沒有加密的.class文件。所以它看起來像父類加載器找到正確的.class文件,並永遠不會調用你的findClass。但是類文件的格式是錯誤的,因爲它是加密的。 序列是my.loadClass-> parent.loadClass-> parent.loadClass ... - > my.findClass

所以你必須確定父類加載器不會找到類。只需重命名加密類別 - 給他們另一個擴展名或保留在單獨的文件夾中。

這應該竅門

+0

我已經嘗試過,但這樣做,我不能趕上ClassFormatError異常!它拋出一種方式! – arash

+0

看// //編輯上面的部分 –

+0

更改加密類的擴展名可能就足夠了。 – rsp