不兼容的魔法值 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);
我不会删除这个post,希望有人会觉得它有用。
我有一个 .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);
我不会删除这个post,希望有人会觉得它有用。