簡體   English   中英

不兼容的魔法值 0 ASM

[英]Incompatible magic value 0 ASM

我有一個 .class 文件,該文件是使用 ASM 核心 API 按以下方式生成的:

public void createEmptyClassWithinPackage(String packageName, String className){
    /* Creating ClassWriter object that creates class in bytecode representation
    *  Flag 0 - no need in computation of stack size and generation of frames */
    ClassWriter classWriter = new ClassWriter(0);
    ClassVisitor classVisitor = new ClassVisitor(ASM4, classWriter) { };

    // Visiting class declaration: version, access, name, generic, super, interface
    classVisitor.visit(V9, ACC_PUBLIC, packageName + className, null,
            Type.getInternalName(Object.class), null);

    // Indicate that generation of class is done and get byte array
    classVisitor.visitEnd();
    classWriter.visitEnd();
    byte[] bytesOfClassToWrite = classWriter.toByteArray();

    checkClassPackage(packageName);
    writeClassToPackage(packageName, className, bytesOfClassToWrite);
}

最后的方法只是檢查目錄並將.class文件寫入其中。 稍后當我想向我正在使用的 class 添加一些東西時:

public void writeEmptyConstructor(String packageName, String className){
    /* Read generated class form package and generate empty constructor */
    byte[] bytesOfClassToRead = readClassFromPackage(packageName, className);

    ClassReader classReader = new ClassReader(bytesOfClassToRead);
    ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES);
    ClassVisitor classVisitor = new ClassVisitor(ASM4, classWriter) { };
    classReader.accept(classVisitor, 0);

    generateDefaultConstructor(classVisitor);

    // Indicate that generation of constructor is done and get byte array
    classVisitor.visitEnd();
    classWriter.visitEnd();
    byte[] bytesOfClassToWrite = classWriter.toByteArray();

    writeClassToPackage(packageName, className, bytesOfClassToWrite);
}

當我嘗試使用 ClassLoader 讀取 Class 時出現問題:

File file = new File("result/classes/TestClass.class");
try(FileInputStream fileInputStream = new FileInputStream(file)) {
    byte[] classByteArray = new byte[(int) file.length()];
    GeneratedClassLoader generatedClassLoader = new GeneratedClassLoader();
    Class c = generatedClassLoader.defineClass("result.classes.TestClass", classByteArray);
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

上面的代碼給出了一個錯誤:

Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 0 in class file result/classes/TestClass
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:878)
    at callers.GeneratedClassLoader.defineClass(GeneratedClassLoader.java:5)
    at Main.main(Main.java:28)

但是當我嘗試使用 ClassLoader 而不在磁盤上寫入字節數組時,它工作得非常好:

    public void createEmptyClassWithinPackage(String packageName, String className){
        /* Creating ClassWriter object that creates class in bytecode representation
        *  Flag 0 - no need in computation of stack size and generation of frames */
        ClassWriter classWriter = new ClassWriter(0);
        ClassVisitor classVisitor = new ClassVisitor(ASM4, classWriter) { };

        // Visiting class declaration: version, access, name, generic, super, interface
        classVisitor.visit(V9, ACC_PUBLIC, packageName + className, null,
                Type.getInternalName(Object.class), null);

        // Indicate that generation of class is done and get byte array
        classVisitor.visitEnd();
        classWriter.visitEnd();
        byte[] bytesOfClassToWrite = classWriter.toByteArray();

        GeneratedClassLoader generatedClassLoader = new GeneratedClassLoader();
        Class c = generatedClassLoader.defineClass((packageName + className).replace("/", ".")
                , bytesOfClassToWrite);

//        checkClassPackage(packageName);
//        writeClassToPackage(packageName, className, bytesOfClassToWrite);
    }

我的問題是:當我從光盤讀取 class 時,魔法值會發生什么? 可能是我不應該使用 ClassLoader 並使用其他東西來讀取.class 文件作為磁盤中的字節數組?

解決方案很簡單,我忘了寫:

fileInputStream.read(classByteArray);

我不會刪除這篇文章,希望有人會覺得它有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM