我目前正在我的 Java 项目中使用
org.objectweb.asm.util.CheckClassAdapter
进行字节码验证。但是,我观察到此类将错误打印到 stderr 而不是抛出异常,这使得以编程方式处理验证失败变得具有挑战性。
这是现有代码片段的示例:
final byte[] bytes = …; // class bytes are generated previously
CheckClassAdapter.verify(
new ClassReader(bytes),
false,
new PrintWriter(System.err)
);
看来潜在的解决方法可能是:
final byte[] bytes = …; // class bytes are generated previously
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
CheckClassAdapter.verify(
new ClassReader(bytes),
false,
pw
);
if (sw.toString().contains("AnalyzerException")) {
System.err.println(sw.toString());
fail();
}
但是,这个解决方案对我来说就像一个“拐杖”。有没有办法修改或扩展
CheckClassAdapter
以使其在字节码验证失败时抛出异常,而不是将错误打印到 stderr?我的目标是捕获并处理代码中的验证错误。任何指导或示例将不胜感激。
ASM版本:
org.ow2.asm:asm:9.6
由于我还没有找到如何使用
CheckClassAdapter
来验证字节码并抛出AnalyzerException
异常,因此我决定按照Holger的建议修改验证方法的源代码。以下是验证字节码的方法:
/**
* Verify the bytecode.
* @param bytes The bytecode to verify.
*/
private void verify(final byte[] bytes) throws AnalyzerException {
final ClassNode clazz = new ClassNode();
new ClassReader(bytes)
.accept(new CheckClassAdapter(clazz, false), ClassReader.SKIP_DEBUG);
final Optional<Type> syper = Optional.ofNullable(clazz.superName).map(Type::getObjectType);
final List<Type> interfaces = clazz.interfaces.stream().map(Type::getObjectType)
.collect(Collectors.toList());
for (final MethodNode method : clazz.methods) {
final SimpleVerifier verifier =
new SimpleVerifier(
Type.getObjectType(clazz.name),
syper.orElse(null),
interfaces,
(clazz.access & Opcodes.ACC_INTERFACE) != 0
);
// You might need to set your own ClassLoader here.
// verifier.setClassLoader(Thread.currentThread().getContextClassLoader());
new Analyzer<>(verifier).analyze(clazz.name, method);
}
}
进口:
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.SimpleVerifier;
import org.objectweb.asm.util.CheckClassAdapter;
另外,值得一提的是,这种方法并不完美,因为您生成字节码然后再次解析它。最有可能的是,您可以通过使用
CheckClassAdapter
和 CheckMethodAdapter
类 将字节码验证直接集成到生成过程中来简化此过程