AspectJ 中 unable to add stackmap attributes 异常的处理

本贴最后更新于 2564 天前,其中的信息可能已经沧海桑田

Aspect 入门 一文

背景

在使用 编译一个 aspect 和一个 jar 文件 来处理 java 1.8 的 jar 包里,出现了异常

org.aspectj.weaver.BCException: Unable to find Asm for stackmap generation (Looking for 'aj.org.objectweb.asm.ClassReader'). Stackmap generation for woven code is required to avoid verify errors on a Java 1.7 or higher runtime
when weaving type org.apache.lucene.queries.BlendedTermQuery$3
when weaving classes
when weaving
when batch building BuildConfig[null] #Files=1 AopXmls=#0

        at org.aspectj.weaver.bcel.LazyClassGen.getJavaClassBytesIncludingReweavable(LazyClassGen.java:703)
        at org.aspectj.weaver.bcel.BcelWeaver.getClassFilesFor(BcelWeaver.java:1443)
        at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1405)
        at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1183)
        at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.weaveQueuedEntries(AjPipeliningCompilerAdapter.java:514)
        at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.queueForWeaving(AjPipeliningCompilerAdapter.java:447)
        at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.afterProcessing(AjPipeliningCompilerAdapter.java:432)
        at org.aspectj.ajdt.internal.compiler.CompilerAdapter.ajc$after$org_aspectj_ajdt_internal_compiler_CompilerAdapter$5$6b855184(CompilerAdapter.aj:103)
        at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:909)
        at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.processCompiledUnits(Compiler.java:550)
        at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:462)
        at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:417)
        at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:1036)
        at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:272)
        at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:185)
        at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:114)
        at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
        at org.aspectj.tools.ajc.Main.run(Main.java:371)
        at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
        at org.aspectj.tools.ajc.Main.main(Main.java:84)

调研

在网上搜索了一遍,观点有两类

  1. 使用了 JDK 1.9,降低到 JDK 1.8 后就好了。然而本 case 中使用的就是 JDK 1.8。
  2. Bug 514062 - Failure duing stackmap generation of @Around call advice on constructor modifying return value。文章中说经过跟踪调试,发现是 classpath 中缺少了某个类包导致的 NPE。但是错误信息中隐藏了 NPE 信息。

ok,那现在只有自己跟踪一下了。

jdb

工具

jdb

方法

jdb -classpath "$ASPECTJ_HOME/lib/aspectjtools.jar:$JAVA_HOME/lib/tools.jar:$CLASSPATH" -Xmx512M org.aspectj.tools.ajc.Main -cp /Users/abeffect/Green/AspectJ/aspectj1.8/lib/aspectjrt.jar:/Users/abeffect/Green/AspectJ/aspectj1.8/lib/aspectJFunctionStats-1.0.2.jar -inpath external-shard-allocation-5.5.0.1.jar ~/Documents/workspace-neon/ess/aspect/RecordFunction.aj -outjar external-shard-allocation-5.5.0.1.aj.jar -1.8

设置断点

> stop in org.aspectj.tools.ajc.Main.runMain
正在延迟断点org.aspectj.tools.ajc.Main.runMain。
将在加载类后设置。
> run
运行org.aspectj.tools.ajc.Main -cp /Users/abeffect/Green/AspectJ/aspectj1.8/lib/aspectjrt.jar:/Users/abeffect/Green/AspectJ/aspectj1.8/lib/aspectJFunctionStats-1.0.2.jar -inpath external-shard-allocation-5.5.0.1.jar /Users/abeffect/Documents/workspace-neon/ess/aspect/RecordFunction.aj -outjar external-shard-allocation-5.5.0.1.aj.jar -1.8
设置未捕获的java.lang.Throwable
设置延迟的未捕获的java.lang.Throwable

>
VM 已启动: 设置延迟的断点org.aspectj.tools.ajc.Main.runMain
断点命中: "线程=main", org.aspectj.tools.ajc.Main.runMain(), 行=225 bci=0

其它调度命令

  • locals:方法参数
  • step:单步
  • print args:打印变量
  • list:查看源代码位置

ide

用 jdb 还是太复杂了,最终还是使用了 ide 来提高效率。

跟踪过程与 Bug 514062 中的一模一样。

  1. 遇到了 AsmDetector.isAsmAround 为 false,然后退出.
  2. 在退出之前,先打出来了一个异常
“AspectJ Internal Error: unable to add stackmap attributes. null”
  1. 异常在 StackMapAdder 类中
java.lang.NullPointerException
	at org.aspectj.weaver.bcel.asm.StackMapAdder$AspectJConnectClassWriter.getCommonSuperClass(StackMapAdder.java:100)
	at aj.org.objectweb.asm.ClassWriter.a(Unknown Source)
	at aj.org.objectweb.asm.Frame.a(Unknown Source)
	at aj.org.objectweb.asm.Frame.a(Unknown Source)
	at aj.org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source)
	at aj.org.objectweb.asm.MethodVisitor.visitMaxs(Unknown Source)
	at aj.org.objectweb.asm.ClassReader.a(Unknown Source)
	at aj.org.objectweb.asm.ClassReader.b(Unknown Source)
	at aj.org.objectweb.asm.ClassReader.accept(Unknown Source)
	at aj.org.objectweb.asm.ClassReader.accept(Unknown Source)
	at org.aspectj.weaver.bcel.asm.StackMapAdder.addStackMaps(StackMapAdder.java:41)
	at org.aspectj.weaver.bcel.LazyClassGen.getJavaClassBytesIncludingReweavable(LazyClassGen.java:705)
	at org.aspectj.weaver.bcel.BcelWeaver.getClassFilesFor(BcelWeaver.java:1443)
	at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1405)
	at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1183)
	at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.weaveQueuedEntries(AjPipeliningCompilerAdapter.java:514)
	at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.queueForWeaving(AjPipeliningCompilerAdapter.java:447)
	at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.afterProcessing(AjPipeliningCompilerAdapter.java:432)
	at org.aspectj.ajdt.internal.compiler.CompilerAdapter.ajc$after$org_aspectj_ajdt_internal_compiler_CompilerAdapter$5$6b855184(CompilerAdapter.aj:103)
	at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:909)
	at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.processCompiledUnits(Compiler.java:550)
	at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:462)
	at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:417)
	at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:1036)
	at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:272)
	at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:185)
	at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:114)
	at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
	at org.aspectj.tools.ajc.Main.run(Main.java:371)
	at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
	at org.aspectj.tools.ajc.Main.main(Main.java:84)
	at MainClass.main(MainClass.java:15)

,由

ClassVisitor cv = new AspectJClassVisitor(cw);
cr.accept(cv, 0);

打出来的,其中 ClassVisitor 是 asm 编写的。

99   resolvedType1 = resolvedType1.getSuperclass();
100  if (resolvedType1.isParameterizedOrGenericType()) {
101	    resolvedType1 = resolvedType1.getRawType();
102  }

100 行的代码如上,其中 resolvedType1 为 null,导致的 NPE。

原因为通过反射来找对应的类没有找到,即 classpath 中缺少类。

解决

修改 classpath,增加上缺少的类后,成功。

总结

如果遇到了异常

AspectJ Internal Error: unable to add stackmap attributes. null

ABORT

打开 org.aspectj.weaver.bcel.asm.StackMapAdder 文件,

在第 100 行设置断点,当其值为 null 时,type1 对应的类,即为缺少的类。

BTW: 在 eclipse 中,可以设置条件断点。方法为:

  1. 断点上右击,点击弹出框最下部的“breakPoint properties”
  2. 选中 Conditional, 这时默认 Suspend when true 单选按钮会选中,就是当条件为 true 时断点会停住

参考资料

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...