2013-08-24 12 views
6

Sto provando a caricare un file jar direttamente nella memoria senza rilasciarlo sull'HDD. Ho provato a utilizzare ClassLoader, ma ottengo un errore.Caricare la matrice di byte del file nella memoria

Questo è il mio codice:

personalizzato programma di caricamento classi

public class CLS_ClassLoader extends ClassLoader { 

    private byte[] bArrData; 

    public CLS_ClassLoader(ClassLoader parent, byte[] bArrData) { 
     super(parent); 

     this.bArrData = bArrData; 
    } 

    public Class<?> loadClass(String name) throws ClassNotFoundException { 
     return defineClass(name, bArrData, 0, 
       bArrData.length); 
    } 
} 

principale

ClassLoader tParentClsLoader = CLS_ClassLoader.class.getClassLoader(); 
CLS_ClassLoader tClsLoader = new CLS_ClassLoader(tParentClsLoader, fileToByteArray("D:/App.jar")); 
Class<?> tClass = null; 

try { 
     tClass = tClsLoader.loadClass("pkg_main.CLS_Main"); 
} catch (ClassNotFoundException e) { 
    e.printStackTrace(); 
} 

uscita

Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1347093252 in class file pkg_main/CLS_Main 
    at java.lang.ClassLoader.defineClass1(Native Method) 
    at java.lang.ClassLoader.defineClass(Unknown Source) 
    at java.lang.ClassLoader.defineClass(Unknown Source) 
    at pkg_main.CLS_ClassLoader.loadClass(CLS_ClassLoader.java:20) 
    at pkg_main.CSL_Main.main(CSL_Main.java:27) 

La mia idea è di prendere un file jar crittografato, decrittarlo in fase di runtime e caricare direttamente in memoria.

Siamo spiacenti per gli errori di battitura, non ho parlato bene l'inglese. Grazie in anticipo!

+1

* "Sto cercando di caricare un file jar direttamente nella memoria senza farla cadere al disco rigido "* Dove sono quei byte che arrivano ** da **? Un URL? Compilato in memoria? Pixies? * "La mia idea è di prendere un file jar crittografato, decrittarlo in runtime e caricarlo direttamente nella memoria." * Questa è una pessima idea. Se è inteso a fermare il furto/decodifica dei codici da parte delle persone, fermerà solo il più dilettante degli hacker. Sono gli hacker con capacità anche moderate di cui devi preoccuparti. –

+0

Hai letto il codice sorgente che ho incollato? se hai letto che avrai visto "fileToByteArray (" D: /App.jar ")". Ho detto, voglio caricare l'array di byte direttamente nella memoria. E penso che sarebbe una buona idea proteggere il mio codice dalla decompilazione. Non serve a un hacker sapere decompilare java. Grazie. –

+1

@ SamuelPedrosa Forse questa risposta aiuterà: http://stackoverflow.com/a/6797331/1531054. Prova a decomprimere il file '.class' da' .jar' e quindi alimentare il suo array di byte al programma di caricamento classi. –

risposta

3

L'errore principale è che defineClass (...) si aspetta byte di classe e lo si sta alimentando con l'intero file jar. L'eccezione effettiva viene generata se i byte di classe non iniziano con 0xCAFEBABE, intestazione tipica del file di classe Java. Quindi, è necessario un ulteriore passaggio per ordinare le classi dal file jar. La seguente implementazione dimostra l'idea:

class CCLoader extends ClassLoader { 
    private Map<String, byte[]> classes = new HashMap<String, byte[]>(); 

    public CCLoader(InputStream in) { 
     super(CCLoader.class.getClassLoader()); 
     try { 
      JarInputStream jis = new JarInputStream(in); 
      JarEntry je = null; 
      String entryName = null; 
      while ((je = jis.getNextJarEntry()) != null) { 
       entryName = je.getName(); 
       if (je.getName().endsWith(".class")) { 
        byte[] classBytes = readClass(jis); 
        String canonicalName = entryName.replaceAll("/", ".").replaceAll(".class", ""); 
        classes.put(canonicalName, classBytes); 
       } 
      } 
      jis.close(); 
      in.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private byte[] readClass(InputStream stream) throws IOException { 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     while(true){ 
      int qwe = stream.read(); 
      if(qwe == -1) break; 
      baos.write(qwe); 
     } 
     return baos.toByteArray(); 
    } 

    public Class loadClass(String name) throws ClassNotFoundException { 
     try { 
      return this.getParent().loadClass(name); 
     } catch (ClassNotFoundException e) { 
      return findClass(name); 
     } 
    } 

    public Class findClass(String name) throws ClassNotFoundException { 
     byte[] classBytes = classes.get(name); 
     return defineClass(name, classBytes, 0, classBytes.length); 
    } 

} 

Seguendo il tuo esempio si può provare così:

ClassLoader tClsLoader = new CCLoader(new FileInputStream("C:/commons-io-2.0.1.jar")); 
Class<?> tClass = tClsLoader.loadClass("org.apache.commons.io.FileExistsException"); 
+0

Lo proverò, grazie :) –

+0

Ho ricevuto questo errore: java.lang.NegativeArraySizeException \t a pkg_main.CCLoader. (CCLoader.java:26) \t a pkg_main.CSL_Main.main (CSL_Main.java:23) –

+0

Mi piace, non è possibile ottenere la dimensione del file di classe. –