6

HDDにドロップせずにjarファイルをメモリに直接ロードしようとしています。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);
    }
}

主要

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

出力

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)

私の考えは、暗号化された jar ファイルを取得し、実行時に復号化し、メモリに直接ロードすることです。

タイプミスでごめんなさい、私は英語を上手に話せませんでした。前もって感謝します!

4

1 に答える 1

3

あなたの主な間違いは、 defineClass(...) がクラスバイトを期待していて、jarファイル全体を供給していることです。クラス バイトが 0xCAFEBABE (典型的な Java クラス ファイル ヘッダー) で始まらない場合、実際の例外がスローされます。そのため、jar ファイルからクラスを分類するための追加の手順が必要です。次の実装は、アイデアを示しています。

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

}

あなたの例に従って、次のように試すことができます:

ClassLoader tClsLoader = new CCLoader(new FileInputStream("C:/commons-io-2.0.1.jar"));
Class<?> tClass = tClsLoader.loadClass("org.apache.commons.io.FileExistsException");
于 2013-08-24T19:01:11.983 に答える