ASM 5.0.3 With Java 1.8 incorrect maxStack with Java.lang.VerifyError: Operand stack overflow

ASM 5.0.3 With Java 1.8 incorrect maxStack with Java.lang.VerifyError: Operand stack overflow

使用 ASM 5.0.3(使用 Java 1.8.0_65 & Tomcat 8.0.30),访问 JSP (date.jsp ) 方法 - _JSP(_jspService) ,低于异常

javax.servlet.ServletException: java.lang.VerifyError: Operand stack overflow
Exception Details:
  Location:
    org/apache/jsp/jsp/dates/date_jsp._jspService(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V @0: aload_1
  Reason:
    Exceeded max stack size.
  Current Frame:
    bci: @0
    flags: { }
    locals: { 'org/apache/jsp/jsp/dates/date_jsp', 'javax/servlet/http/HttpServletRequest', 'javax/servlet/http/HttpServletResponse' }
    stack: { }
  Bytecode: .......................

注意:我没有更改方法的字节码,只是访问使用 ASM 5.0.3 的 MethodVisitor class 的方法。

date.jsp

<html>
<%@ page session="false"%>
    <body>
        <jsp:useBean id='clock' scope='page' class='dates.JspCalendar' type="dates.JspCalendar"/>
    </body>
</html>

注意: 如果我删除 <jsp:useBean ..../> , JSP 页面执行正常并且没有得到任何 java.lang.VerifyError

另附上我的代码大纲:

public byte[] transform(ClassLoader loader, String className, Class<?> 
                        classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException{ 
            if(!className.equals("org/apache/jsp/jsp/dates/date_jsp")){
                return classfileBuffer;
            }
            ClassReader classReader = null;
            try{
                classReader=new ClassReader(classfileBuffer);
            }
            catch(Throwable exp){
                return classfileBuffer;
            }

        int writerFlag = ClassWriter.COMPUTE_MAXS;
        int accpetFlag = ClassReader.EXPAND_FRAMES;
        int classFileversion = getClassJavaVersion(classReader);
        if(classFileversion > 50){
            writerFlag = ClassWriter.COMPUTE_FRAMES;
            accpetFlag = ClassReader.SKIP_FRAMES;
        }
        ClassWriter classWriter = new ClassWriter(classReader, writerFlag);
        ClassVisitor classVisitor =(ClassVisitor) new MiniJSPClassVisitor(classWriter , className,  classFileversion);
        if(classVisitor!=null){
            try{
                classReader.accept(classVisitor, accpetFlag); 
            }catch(Exception e) {}
            finally{
                classfileBuffer =  classWriter.toByteArray();
            }
        }
        return classfileBuffer;
    }

    private static int getClassJavaVersion(ClassReader classReader) {
        return classReader.readUnsignedShort(6);
    }`

注意:编译的JSPclass版本是51,所以ASM使用,ClassWriter.COMPUTE_FRAMESClassReader.SKIP_FRAMES

MiniJSPClassVisitor.java

public class MiniJSPClassVisitor extends ClassVisitor {

    private static final String _jspServiceDesc = "(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V";

    public MiniJSPClassVisitor(ClassVisitor classVisitor , String className,  int classFileVersion) {
        super(Opcodes.ASM5 , classVisitor);
    }

    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        MethodVisitor mv;
        mv = super.visitMethod(access, name, desc, signature, exceptions);
        if (mv != null) {
            if ((access & Opcodes.ACC_NATIVE) != 0 || (access & Opcodes.ACC_ABSTRACT) != 0){
                return mv;
            }
            if(name.equals("<clinit>") || name.equals("<init>") || name.equals("init")){
                return mv;
            }
            if(name.equals("_jspService") && desc.equals(_jspServiceDesc)){
                mv = new SimpleMethodVisitor(Opcodes.ASM5 , mv , name);
            }
            return mv;
        }
        return null;
    }
}

SimpleMethodVisitor.java

public class SimpleMethodVisitor extends MethodVisitor {
    private String methodName = null;

    public SimpleMethodVisitor(int api, MethodVisitor mv, String methodName) {
        super(Opcodes.ASM5, mv);
        this.methodName = methodName;
        System.out.println("SimpleMethodVisitor :"+methodName );
    }

我使用 TraceClassVisitor

在有和没有访问 _jspService 方法的情况下打印了 class - org/apache/jsp/jsp/dates/date_jsp 的字节码
pw = new PrintWriter(homeFolder + File.separator + "date.log");
ClassReader cr = new ClassReader(classfileBuffer);
cr.accept(new TraceClassVisitor(null, new ASMifier(), pw), ClassReader.EXPAND_FRAMES);

似乎 ASM 在访问 _jspService 方法时计算了错误的最大堆栈 - mv.visitMaxs(0, 10) 而不是 mv.visitMaxs(8, 10)

附上正确最大堆栈的屏幕截图

错误的最大筹码

作为参考,附上 _jspService 方法的编译版本

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}

    final javax.servlet.jsp.PageContext pageContext;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, false, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("<html>\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("<body>\r\n");
      dates.JspCalendar clock = null;
      clock = (dates.JspCalendar) _jspx_page_context.getAttribute("clock", javax.servlet.jsp.PageContext.PAGE_SCOPE);
      if (clock == null){
        clock = new dates.JspCalendar();
        _jspx_page_context.setAttribute("clock", clock, javax.servlet.jsp.PageContext.PAGE_SCOPE);
      }
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("</body>\r\n");
      out.write("</html>\r\n");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

如何解决声明 JSP Bean 时发生的 java.lang.VerifyError? (要么) 需要在 ASM 方面做些什么来克服这个问题?提前致谢

注:

相同的代码适用于 Java 6 和 Tomcat 6

编辑 #1,Holger 附加了方法 _jspService 的字节码。

{
mv = cw.visitMethod(ACC_PUBLIC, "_jspService", "(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V", null, new String[] { "java/io/IOException", "javax/servlet/ServletException" });
mv.visitCode();
Label l0 = new Label();
Label l1 = new Label();
Label l2 = new Label();
mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
Label l3 = new Label();
Label l4 = new Label();
Label l5 = new Label();
mv.visitTryCatchBlock(l3, l4, l5, "java/io/IOException");
Label l6 = new Label();
Label l7 = new Label();
mv.visitTryCatchBlock(l0, l6, l7, null);
Label l8 = new Label();
mv.visitLabel(l8);
mv.visitLineNumber(82, l8);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletRequest", "getMethod", "()Ljava/lang/String;", true);
mv.visitVarInsn(ASTORE, 3);
Label l9 = new Label();
mv.visitLabel(l9);
mv.visitLineNumber(83, l9);
mv.visitLdcInsn("GET");
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
Label l10 = new Label();
mv.visitJumpInsn(IFNE, l10);
mv.visitLdcInsn("POST");
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
mv.visitJumpInsn(IFNE, l10);
mv.visitLdcInsn("HEAD");
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
mv.visitJumpInsn(IFNE, l10);
mv.visitFieldInsn(GETSTATIC, "javax/servlet/DispatcherType", "ERROR", "Ljavax/servlet/DispatcherType;");
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletRequest", "getDispatcherType", "()Ljavax/servlet/DispatcherType;", true);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/DispatcherType", "equals", "(Ljava/lang/Object;)Z", false);
mv.visitJumpInsn(IFNE, l10);
Label l11 = new Label();
mv.visitLabel(l11);
mv.visitLineNumber(84, l11);
mv.visitVarInsn(ALOAD, 2);
mv.visitIntInsn(SIPUSH, 405);
mv.visitLdcInsn("JSPs only permit GET POST or HEAD");
mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletResponse", "sendError", "(ILjava/lang/String;)V", true);
Label l12 = new Label();
mv.visitLabel(l12);
mv.visitLineNumber(85, l12);
mv.visitInsn(RETURN);
mv.visitLabel(l10);
mv.visitLineNumber(91, l10);
mv.visitInsn(ACONST_NULL);
mv.visitVarInsn(ASTORE, 5);
Label l13 = new Label();
mv.visitLabel(l13);
mv.visitLineNumber(93, l13);
mv.visitInsn(ACONST_NULL);
mv.visitVarInsn(ASTORE, 6);
Label l14 = new Label();
mv.visitLabel(l14);
mv.visitLineNumber(94, l14);
mv.visitInsn(ACONST_NULL);
mv.visitVarInsn(ASTORE, 7);
mv.visitLabel(l0);
mv.visitLineNumber(98, l0);
mv.visitVarInsn(ALOAD, 2);
mv.visitLdcInsn("text/html");
mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletResponse", "setContentType", "(Ljava/lang/String;)V", true);
Label l15 = new Label();
mv.visitLabel(l15);
mv.visitLineNumber(99, l15);
mv.visitFieldInsn(GETSTATIC, "org/apache/jsp/jsp/dates/date_jsp", "_jspxFactory", "Ljavax/servlet/jsp/JspFactory;");
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
Label l16 = new Label();
mv.visitLabel(l16);
mv.visitLineNumber(100, l16);
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ICONST_0);
mv.visitIntInsn(SIPUSH, 8192);
mv.visitInsn(ICONST_1);
Label l17 = new Label();
mv.visitLabel(l17);
mv.visitLineNumber(99, l17);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspFactory", "getPageContext", "(Ljavax/servlet/Servlet;Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljava/lang/String;ZIZ)Ljavax/servlet/jsp/PageContext;", false);
mv.visitVarInsn(ASTORE, 4);
Label l18 = new Label();
mv.visitLabel(l18);
mv.visitLineNumber(101, l18);
mv.visitVarInsn(ALOAD, 4);
mv.visitVarInsn(ASTORE, 7);
Label l19 = new Label();
mv.visitLabel(l19);
mv.visitLineNumber(102, l19);
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/PageContext", "getServletContext", "()Ljavax/servlet/ServletContext;", false);
mv.visitInsn(POP);
Label l20 = new Label();
mv.visitLabel(l20);
mv.visitLineNumber(103, l20);
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/PageContext", "getServletConfig", "()Ljavax/servlet/ServletConfig;", false);
mv.visitInsn(POP);
Label l21 = new Label();
mv.visitLabel(l21);
mv.visitLineNumber(104, l21);
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/PageContext", "getOut", "()Ljavax/servlet/jsp/JspWriter;", false);
mv.visitVarInsn(ASTORE, 5);
Label l22 = new Label();
mv.visitLabel(l22);
mv.visitLineNumber(105, l22);
mv.visitVarInsn(ALOAD, 5);
mv.visitVarInsn(ASTORE, 6);
Label l23 = new Label();
mv.visitLabel(l23);
mv.visitLineNumber(107, l23);
mv.visitVarInsn(ALOAD, 5);
mv.visitLdcInsn("<html>\r\n");
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "write", "(Ljava/lang/String;)V", false);
Label l24 = new Label();
mv.visitLabel(l24);
mv.visitLineNumber(108, l24);
mv.visitVarInsn(ALOAD, 5);
mv.visitLdcInsn("\r\n");
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "write", "(Ljava/lang/String;)V", false);
Label l25 = new Label();
mv.visitLabel(l25);
mv.visitLineNumber(109, l25);
mv.visitVarInsn(ALOAD, 5);
mv.visitLdcInsn("\u0009<body>\r\n");
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "write", "(Ljava/lang/String;)V", false);
Label l26 = new Label();
mv.visitLabel(l26);
mv.visitLineNumber(110, l26);
mv.visitVarInsn(ALOAD, 5);
mv.visitLdcInsn("\u0009\u0009");
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "write", "(Ljava/lang/String;)V", false);
Label l27 = new Label();
mv.visitLabel(l27);
mv.visitLineNumber(111, l27);
mv.visitInsn(ACONST_NULL);
mv.visitVarInsn(ASTORE, 8);
Label l28 = new Label();
mv.visitLabel(l28);
mv.visitLineNumber(112, l28);
mv.visitVarInsn(ALOAD, 7);
mv.visitLdcInsn("clock");
mv.visitInsn(ICONST_1);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/PageContext", "getAttribute", "(Ljava/lang/String;I)Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, "dates/JspCalendar");
mv.visitVarInsn(ASTORE, 8);
Label l29 = new Label();
mv.visitLabel(l29);
mv.visitLineNumber(113, l29);
mv.visitVarInsn(ALOAD, 8);
Label l30 = new Label();
mv.visitJumpInsn(IFNONNULL, l30);
Label l31 = new Label();
mv.visitLabel(l31);
mv.visitLineNumber(114, l31);
mv.visitTypeInsn(NEW, "dates/JspCalendar");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "dates/JspCalendar", "<init>", "()V", false);
mv.visitVarInsn(ASTORE, 8);
Label l32 = new Label();
mv.visitLabel(l32);
mv.visitLineNumber(115, l32);
mv.visitVarInsn(ALOAD, 7);
mv.visitLdcInsn("clock");
mv.visitVarInsn(ALOAD, 8);
mv.visitInsn(ICONST_1);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/PageContext", "setAttribute", "(Ljava/lang/String;Ljava/lang/Object;I)V", false);
mv.visitLabel(l30);
mv.visitLineNumber(117, l30);
mv.visitVarInsn(ALOAD, 5);
mv.visitLdcInsn("\r\n");
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "write", "(Ljava/lang/String;)V", false);
Label l33 = new Label();
mv.visitLabel(l33);
mv.visitLineNumber(118, l33);
mv.visitVarInsn(ALOAD, 5);
mv.visitLdcInsn("\u0009</body>\r\n");
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "write", "(Ljava/lang/String;)V", false);
Label l34 = new Label();
mv.visitLabel(l34);
mv.visitLineNumber(119, l34);
mv.visitVarInsn(ALOAD, 5);
mv.visitLdcInsn("</html>\r\n");
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "write", "(Ljava/lang/String;)V", false);
mv.visitLabel(l1);
mv.visitLineNumber(120, l1);
Label l35 = new Label();
mv.visitJumpInsn(GOTO, l35);
mv.visitLabel(l2);
mv.visitVarInsn(ASTORE, 8);
Label l36 = new Label();
mv.visitLabel(l36);
mv.visitLineNumber(121, l36);
mv.visitVarInsn(ALOAD, 8);
mv.visitTypeInsn(INSTANCEOF, "javax/servlet/jsp/SkipPageException");
mv.visitJumpInsn(IFNE, l6);
Label l37 = new Label();
mv.visitLabel(l37);
mv.visitLineNumber(122, l37);
mv.visitVarInsn(ALOAD, 6);
mv.visitVarInsn(ASTORE, 5);
Label l38 = new Label();
mv.visitLabel(l38);
mv.visitLineNumber(123, l38);
mv.visitVarInsn(ALOAD, 5);
Label l39 = new Label();
mv.visitJumpInsn(IFNULL, l39);
mv.visitVarInsn(ALOAD, 5);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "getBufferSize", "()I", false);
mv.visitJumpInsn(IFEQ, l39);
mv.visitLabel(l3);
mv.visitLineNumber(125, l3);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletResponse", "isCommitted", "()Z", true);
Label l40 = new Label();
mv.visitJumpInsn(IFEQ, l40);
Label l41 = new Label();
mv.visitLabel(l41);
mv.visitLineNumber(126, l41);
mv.visitVarInsn(ALOAD, 5);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "flush", "()V", false);
Label l42 = new Label();
mv.visitLabel(l42);
mv.visitLineNumber(127, l42);
mv.visitJumpInsn(GOTO, l39);
mv.visitLabel(l40);
mv.visitLineNumber(128, l40);
mv.visitVarInsn(ALOAD, 5);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspWriter", "clearBuffer", "()V", false);
mv.visitLabel(l4);
mv.visitLineNumber(130, l4);
mv.visitJumpInsn(GOTO, l39);
mv.visitLabel(l5);
mv.visitInsn(POP);
mv.visitLabel(l39);
mv.visitLineNumber(131, l39);
mv.visitVarInsn(ALOAD, 7);
Label l43 = new Label();
mv.visitJumpInsn(IFNULL, l43);
mv.visitVarInsn(ALOAD, 7);
mv.visitVarInsn(ALOAD, 8);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/PageContext", "handlePageException", "(Ljava/lang/Throwable;)V", false);
mv.visitJumpInsn(GOTO, l6);
mv.visitLabel(l43);
mv.visitLineNumber(132, l43);
mv.visitTypeInsn(NEW, "javax/servlet/ServletException");
mv.visitInsn(DUP);
mv.visitVarInsn(ALOAD, 8);
mv.visitMethodInsn(INVOKESPECIAL, "javax/servlet/ServletException", "<init>", "(Ljava/lang/Throwable;)V", false);
mv.visitInsn(ATHROW);
mv.visitLabel(l6);
mv.visitLineNumber(135, l6);
mv.visitFieldInsn(GETSTATIC, "org/apache/jsp/jsp/dates/date_jsp", "_jspxFactory", "Ljavax/servlet/jsp/JspFactory;");
mv.visitVarInsn(ALOAD, 7);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspFactory", "releasePageContext", "(Ljavax/servlet/jsp/PageContext;)V", false);
Label l44 = new Label();
mv.visitJumpInsn(GOTO, l44);
mv.visitLabel(l7);
mv.visitLineNumber(134, l7);
mv.visitVarInsn(ASTORE, 9);
Label l45 = new Label();
mv.visitLabel(l45);
mv.visitLineNumber(135, l45);
mv.visitFieldInsn(GETSTATIC, "org/apache/jsp/jsp/dates/date_jsp", "_jspxFactory", "Ljavax/servlet/jsp/JspFactory;");
mv.visitVarInsn(ALOAD, 7);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspFactory", "releasePageContext", "(Ljavax/servlet/jsp/PageContext;)V", false);
Label l46 = new Label();
mv.visitLabel(l46);
mv.visitLineNumber(136, l46);
mv.visitVarInsn(ALOAD, 9);
mv.visitInsn(ATHROW);
mv.visitLabel(l35);
mv.visitLineNumber(135, l35);
mv.visitFieldInsn(GETSTATIC, "org/apache/jsp/jsp/dates/date_jsp", "_jspxFactory", "Ljavax/servlet/jsp/JspFactory;");
mv.visitVarInsn(ALOAD, 7);
mv.visitMethodInsn(INVOKEVIRTUAL, "javax/servlet/jsp/JspFactory", "releasePageContext", "(Ljavax/servlet/jsp/PageContext;)V", false);
mv.visitLabel(l44);
mv.visitLineNumber(137, l44);
mv.visitInsn(RETURN);
Label l47 = new Label();
mv.visitLabel(l47);
mv.visitLocalVariable("this", "Lorg/apache/jsp/jsp/dates/date_jsp;", null, l8, l47, 0);
mv.visitLocalVariable("request", "Ljavax/servlet/http/HttpServletRequest;", null, l8, l47, 1);
mv.visitLocalVariable("response", "Ljavax/servlet/http/HttpServletResponse;", null, l8, l47, 2);
mv.visitLocalVariable("_jspx_method", "Ljava/lang/String;", null, l9, l47, 3);
mv.visitLocalVariable("pageContext", "Ljavax/servlet/jsp/PageContext;", null, l18, l1, 4);
mv.visitLocalVariable("out", "Ljavax/servlet/jsp/JspWriter;", null, l13, l47, 5);
mv.visitLocalVariable("_jspx_out", "Ljavax/servlet/jsp/JspWriter;", null, l14, l47, 6);
mv.visitLocalVariable("_jspx_page_context", "Ljavax/servlet/jsp/PageContext;", null, l0, l47, 7);
mv.visitLocalVariable("clock", "Ldates/JspCalendar;", null, l28, l1, 8);
mv.visitLocalVariable("t", "Ljava/lang/Throwable;", null, l36, l6, 8);
mv.visitMaxs(0, 10);
mv.visitEnd();
}

我找到了使用 java 1.7 和 1.8

解决此类 VerifyError 的解决方案

MyClassFileTransformertransform() 方法中,我替换了行

ClassWriter classWriter = new ClassWriter(classReader, writerFlag); 换行 ClassWriter classWriter = new ByteCodeWriter(classReader, loader, writerFlag);

ByteCodeWriter.java

`

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;

public class ByteCodeWriter extends ClassWriter
{
  static final String OBJECT_REPRESENTATION = "java/lang/Object";
  ClassLoader classLoader;

  public ByteCodeWriter(ClassReader classReader, ClassLoader loader, int writerFlag)
  {
    super(classReader, writerFlag);
    this.classLoader = loader;
  }

  protected String getCommonSuperClass(String className1, String className2)
  {
    Class class1;
    Class class2;
    try
    {
      class1 = Class.forName(className1.replace('/', '.'), false, this.classLoader);
      class2 = Class.forName(className2.replace('/', '.'), false, this.classLoader);
    }
    catch (Exception th) {
      throw new RuntimeException(th.getMessage());
    }

    if (class1.isAssignableFrom(class2)) {
      return className1;
    }
    if (class2.isAssignableFrom(class1)) {
      return className2;
    }

    if ((class1.isInterface()) || (class2.isInterface())) {
      return "java/lang/Object";
    }

    do {
      class1 = class1.getSuperclass();
    }
    while (!(class1.isAssignableFrom(class2)));
    return class1.getName().replace('.', '/');
  }
}`

基本上我扩展 ClassWriter class 并覆盖方法 getCommonSuperClass

Error while instrumenting class files (asm.ClassWriter.getCommonSuperClass) 帮我解决了这个问题。

但我不知道,有什么必要覆盖getCommonSuperClass