我找到了一个解决方案,创建了一个扩展 CheckClassAdapter 的类并添加了一个带有 ClassNode 参数的方法。阅读 CheckClassAdapter 的源码,我发现 ClassReader 还是访问了一个类节点。
public static void verify(
final ClassReader classReader,
final ClassLoader loader,
final boolean printResults,
final PrintWriter printWriter) {
ClassNode classNode = new ClassNode();
classReader.accept(
new CheckClassAdapter(/*latest*/ Opcodes.ASM10_EXPERIMENTAL, classNode, false) {},
ClassReader.SKIP_DEBUG);
如您所见,ASM 可以公开一个方法,只在 ClassNode 中输入,但由于某种原因没有。
这是扩展 CheckClassAdapter 的类的代码,添加了此功能:
public class CheckClassAdapterClassNode extends CheckClassAdapter {
public CheckClassAdapterClassNode(ClassVisitor classVisitor) {
super(classVisitor);
}
/**
* Checks the given class.
*
* @param classNode the class to be checked.
* @param loader a <code>ClassLoader</code> which will be used to load referenced classes. May be
* {@literal null}.
* @param printResults whether to print the results of the bytecode verification.
* @param printWriter where the results (or the stack trace in case of error) must be printed.
*/
public static void verify(
final ClassNode classNode,
final ClassLoader loader,
final boolean printResults,
final PrintWriter printWriter) {
Type syperType = classNode.superName == null ? null : Type.getObjectType(classNode.superName);
List<MethodNode> methods = classNode.methods;
List<Type> interfaces = new ArrayList<>();
for (String interfaceName : classNode.interfaces) {
interfaces.add(Type.getObjectType(interfaceName));
}
for (MethodNode method : methods) {
SimpleVerifier verifier =
new SimpleVerifier(
Type.getObjectType(classNode.name),
syperType,
interfaces,
(classNode.access & Opcodes.ACC_INTERFACE) != 0);
Analyzer<BasicValue> analyzer = new Analyzer<>(verifier);
if (loader != null) {
verifier.setClassLoader(loader);
}
try {
analyzer.analyze(classNode.name, method);
} catch (AnalyzerException e) {
e.printStackTrace(printWriter);
}
if (printResults) {
printAnalyzerResult(method, analyzer, printWriter);
}
}
printWriter.flush();
}
static void printAnalyzerResult(
final MethodNode method, final Analyzer<BasicValue> analyzer, final PrintWriter printWriter) {
Textifier textifier = new Textifier();
TraceMethodVisitor traceMethodVisitor = new TraceMethodVisitor(textifier);
printWriter.println(method.name + method.desc);
for (int i = 0; i < method.instructions.size(); ++i) {
if (method.instructions.get(i) == null) continue;
method.instructions.get(i).accept(traceMethodVisitor);
StringBuilder stringBuilder = new StringBuilder();
Frame<BasicValue> frame = analyzer.getFrames()[i];
if (frame == null) {
stringBuilder.append('?');
} else {
for (int j = 0; j < frame.getLocals(); ++j) {
stringBuilder.append(getUnqualifiedName(frame.getLocal(j).toString())).append(' ');
}
stringBuilder.append(" : ");
for (int j = 0; j < frame.getStackSize(); ++j) {
stringBuilder.append(getUnqualifiedName(frame.getStack(j).toString())).append(' ');
}
}
while (stringBuilder.length() < method.maxStack + method.maxLocals + 1) {
stringBuilder.append(' ');
}
printWriter.print(Integer.toString(i + 100000).substring(1));
printWriter.print(
" " + stringBuilder + " : " + textifier.text.get(textifier.text.size() - 1));
}
for (TryCatchBlockNode tryCatchBlock : method.tryCatchBlocks) {
tryCatchBlock.accept(traceMethodVisitor);
printWriter.print(" " + textifier.text.get(textifier.text.size() - 1));
}
printWriter.println();
}
private static String getUnqualifiedName(final String name) {
int lastSlashIndex = name.lastIndexOf('/');
if (lastSlashIndex == -1) {
return name;
} else {
int endIndex = name.length();
if (name.charAt(endIndex - 1) == ';') {
endIndex--;
}
return name.substring(lastSlashIndex + 1, endIndex);
}
}
}
我可能会在 ASM 存储库上创建一个问题并添加一个拉取请求来添加它。