2013-08-24 12 views
6

Próbuję załadować plik JAR bezpośrednio do pamięci bez upuszczania go na dysk twardy. Próbowałem używać ClassLoader, ale pojawia się błąd.Załaduj tablicę bajtów pliku do pamięci

To jest mój kod:

niestandardowe classloader

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); 
    } 
} 

główna

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(); 
} 

Wyjście

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) 

Moim zamysłem jest zaszyfrować plik JAR, zaszyfrować go w środowisku wykonawczym i załadować bezpośrednio do pamięci.

Przepraszam za literówki, nie mówiłem dobrze po angielsku. Z góry dziękuję!

+1

* "Próbuję załadować plik jar bezpośrednio do pamięci bez upuszczenie go na dysku twardym "* Gdzie są te bajty przychodzące ** od **? Adres URL? Skompilowany w pamięci? Pixies? * "Moim pomysłem jest zaszyfrowanie pliku JAR, odszyfrowanie go w środowisku wykonawczym i załadowanie bezpośrednio do pamięci." * To kiepski pomysł. Jeśli ma to na celu powstrzymanie kradzieży/inżynierii wstecznej kodów ", zatrzyma tylko najbardziej amatorów hakerów. To hakerzy z nawet umiarkowanymi umiejętnościami, o które musisz się martwić. –

+0

Czy przeczytałeś kod źródłowy, który wkleiłem? jeśli przeczytałeś, że zobaczysz "fileToByteArray (" D: /App.jar ")". Powiedziałem, chcę załadować tablicę bajtów bezpośrednio do pamięci. Myślę, że dobrym pomysłem byłoby zabezpieczenie mojego kodu przed dekompilacją. Nie trzeba hakera, aby wiedzieć, jak dekompilować java. Dzięki. –

+1

@SamuelPedrosa Być może ta odpowiedź pomoże: http://stackoverflow.com/a/6797331/1531054. Spróbuj rozpakować plik '.class' z' .jar', a następnie załaduj jego tablicę bajtów do programu ładującego klasy. –

Odpowiedz

3

Twoim głównym błędem jest to, że defineClass (...) oczekuje bajtów klasy i karmisz go całym plikiem jar. Rzeczywisty wyjątek jest generowany, jeśli bajty klas nie zaczynają się od 0xCAFEBABE, typowego nagłówka pliku klasy Java. Potrzebujesz więc dodatkowego kroku, aby posortować klasy z pliku JAR. Poniższy wdrożenie demonstruje pomysł:

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); 
    } 

} 

po swój przykład można spróbować go tak:

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

Spróbuję, dzięki :) –

+0

Otrzymuję ten błąd: java.lang.NegativeArraySizeException \t na pkg_main.CCLoader. (CCLoader.java:26) \t na pkg_main.CSL_Main.main (CSL_Main.java:23) –

+0

Wygląda na to, że nie może uzyskać rozmiaru pliku klasy. –

Powiązane problemy