2010-02-17 3 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

установка Try Загрузчик классов и посмотрите программно, если он работает

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