简体   繁体   中英

Java Byte code Manipulation with ASM

I'm using ASM 3.3.1. I am trying to intercept a class and change one of it's methods. I am using the org.objectweb.asm.util.ASMifierClassVisitor to get ASM code to make the new method. Everything works great but I can't asmify if() statements. When I try to use the resulting asm code with an if statement (or loops) in it, I get a “stack size too large” error at runtime. I am using ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);. This is the ASMIFY code it gives me.

Do you have any idea why I would only get an error when i'm ASMIFYING if() statements? I would greatly greatly appreciate any help.

`mv = cw.visitMethod(ACC_PUBLIC, "doWrite", "(Lorg/apache/tomcat/util/buf/ByteChunk;)V", null, new String[] { "java/io/IOException" });
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "org/apache/coyote/Response", "req", "Lorg/apache/coyote/Request;");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/coyote/Request", "getParameters", "()Lorg/apache/tomcat/util/http/Parameters;");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/tomcat/util/http/Parameters", "paramsAsString", "()Ljava/lang/String;");
mv.visitVarInsn(ASTORE, 2);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V");
mv.visitLdcInsn("The Parameters are: ");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "org/apache/coyote/Response", "req", "Lorg/apache/coyote/Request;");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/coyote/Request", "getParameters", "()Lorg/apache/tomcat/util/http/Parameters;");
mv.visitLdcInsn("json");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/tomcat/util/http/Parameters", "getParameter", "(Ljava/lang/String;)Ljava/lang/String;");
mv.visitVarInsn(ASTORE, 3);
mv.visitVarInsn(ALOAD, 3);
Label l0 = new Label();
mv.visitJumpInsn(IFNULL, l0);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("###%#%#%$%#%#%#%#%#%#%#%##%#");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
mv.visitLabel(l0);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V");
mv.visitLdcInsn("Headers: ");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "org/apache/coyote/Response", "headers", "Lorg/apache/tomcat/util/http/MimeHeaders;");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/tomcat/util/http/MimeHeaders", "toString", "()Ljava/lang/String;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitLdcInsn("\n");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V");
mv.visitLdcInsn("Writeing: ");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/tomcat/util/buf/ByteChunk", "toString", "()Ljava/lang/String;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitLdcInsn("\n");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "org/apache/coyote/Response", "outputBuffer", "Lorg/apache/coyote/OutputBuffer;");
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/coyote/OutputBuffer", "doWrite", "(Lorg/apache/tomcat/util/buf/ByteChunk;Lorg/apache/coyote/Response;)I");
mv.visitInsn(POP);
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitFieldInsn(GETFIELD, "org/apache/coyote/Response", "bytesWritten", "J");
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/tomcat/util/buf/ByteChunk", "getLength", "()I");
mv.visitInsn(I2L);
mv.visitInsn(LADD);
mv.visitFieldInsn(PUTFIELD, "org/apache/coyote/Response", "bytesWritten", "J");
mv.visitInsn(RETURN);
mv.visitMaxs(5, 4);
mv.visitEnd();
`

The Code I am ASMifying. (Note: I've taken out the method as that's all I'm using)

public void doWrite(ByteChunk chunk/*byte buffer[], int pos, int count*/)
        throws IOException
    {

        String params=req.getParameters().paramsAsString();

        System.out.println("The Parameters are: "+params);

        String reqParam = req.getParameters().getParameter("json");

        if(reqParam != null)
        {
            System.out.println("###%#%#%$%#%#%#%#%#%#%#%##%#");
        }

        System.out.println("Headers: " + headers.toString()+ "\n");
        System.out.println("Writeing: " +chunk.toString()+"\n");


        outputBuffer.doWrite(chunk, this);
        bytesWritten+=chunk.getLength();
    }

The original method just contains the last two lines

outputBuffer.doWrite(chunk, this);
bytesWritten+=chunk.getLength();

This Doesn't look good. I used the CheckClassAdapter.verify() method and got this for the part of class I'm messing with.

doWrite(Lorg/apache/tomcat/util/buf/ByteChunk;)V
00000 Response ByteChunk . .  :  :    FRAME FULL [] []
00001 Response ByteChunk . .  :  :     ALOAD 0
00002 Response ByteChunk . .  : Response  :     GETFIELD org/apache/coyote/Response.req : Lorg/apache/coyote/Request;
00003 Response ByteChunk . .  : Request  :     INVOKEVIRTUAL org/apache/coyote/Request.getParameters ()Lorg/apache/tomcat/util/http/Parameters;
00004 Response ByteChunk . .  : Parameters  :     INVOKEVIRTUAL org/apache/tomcat/util/http/Parameters.paramsAsString ()Ljava/lang/String;
00005 Response ByteChunk . .  : String  :     ASTORE 2
00006 Response ByteChunk String .  :  :     GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
00007 Response ByteChunk String .  : PrintStream  :     NEW java/lang/StringBuilder
00008 Response ByteChunk String .  : PrintStream StringBuilder  :     DUP
00009 Response ByteChunk String .  : PrintStream StringBuilder StringBuilder  :     INVOKESPECIAL java/lang/StringBuilder.<init> ()V
00010 Response ByteChunk String .  : PrintStream StringBuilder  :     LDC "The Parameters are: "
00011 Response ByteChunk String .  : PrintStream StringBuilder String  :     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
00012 Response ByteChunk String .  : PrintStream StringBuilder  :     ALOAD 2
00013 Response ByteChunk String .  : PrintStream StringBuilder String  :     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
00014 Response ByteChunk String .  : PrintStream StringBuilder  :     INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
00015 Response ByteChunk String .  : PrintStream String  :     INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
00016 Response ByteChunk String .  :  :     ALOAD 0
00017 Response ByteChunk String .  : Response  :     GETFIELD org/apache/coyote/Response.req : Lorg/apache/coyote/Request;
00018 Response ByteChunk String .  : Request  :     INVOKEVIRTUAL org/apache/coyote/Request.getParameters ()Lorg/apache/tomcat/util/http/Parameters;
00019 Response ByteChunk String .  : Parameters  :     LDC "json"
00020 Response ByteChunk String .  : Parameters String  :     INVOKEVIRTUAL org/apache/tomcat/util/http/Parameters.getParameter (Ljava/lang/String;)Ljava/lang/String;
00021 Response ByteChunk String .  : String  :     ASTORE 3
00022 Response ByteChunk String String  :  :     ALOAD 3
00023 Response ByteChunk String String  : String  :     IFNULL L0
00024 Response ByteChunk String String  :  :     GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
00025 Response ByteChunk String String  : PrintStream  :     LDC "###%#%#%$%#%#%#%#%#%#%#%##%#"
00026 Response ByteChunk String String  : PrintStream String  :     INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
00027 Response ByteChunk String String  :  :    L0
00028 Response ByteChunk String String  :  :    FRAME FULL [org/apache/coyote/Response org/apache/tomcat/
00029 Response ByteChunk String String  :  :     GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
00030 Response ByteChunk String String  : PrintStream  :     NEW java/lang/StringBuilder
00031 Response ByteChunk String String  : PrintStream StringBuilder  :     DUP
00032 Response ByteChunk String String  : PrintStream StringBuilder StringBuilder  :     INVOKESPECIAL java/lang/StringBuilder.<init> ()V
00033 Response ByteChunk String String  : PrintStream StringBuilder  :     LDC "Headers: "
00034 Response ByteChunk String String  : PrintStream StringBuilder String  :     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
00035 Response ByteChunk String String  : PrintStream StringBuilder  :     ALOAD 0
00036 Response ByteChunk String String  : PrintStream StringBuilder Response  :     GETFIELD org/apache/coyote/Response.headers : Lorg/apache/tomcat/util/http/MimeHeaders;
00037 Response ByteChunk String String  : PrintStream StringBuilder MimeHeaders  :     INVOKEVIRTUAL org/apache/tomcat/util/http/MimeHeaders.toString ()Ljava/lang/String;
00038 Response ByteChunk String String  : PrintStream StringBuilder String  :     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
00039 Response ByteChunk String String  : PrintStream StringBuilder  :     LDC "\n"
00040 Response ByteChunk String String  : PrintStream StringBuilder String  :     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
00041 Response ByteChunk String String  : PrintStream StringBuilder  :     INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
00042 Response ByteChunk String String  : PrintStream String  :     INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
00043 Response ByteChunk String String  :  :     GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
00044 Response ByteChunk String String  : PrintStream  :     NEW java/lang/StringBuilder
00045 Response ByteChunk String String  : PrintStream StringBuilder  :     DUP
00046 Response ByteChunk String String  : PrintStream StringBuilder StringBuilder  :     INVOKESPECIAL java/lang/StringBuilder.<init> ()V
00047 Response ByteChunk String String  : PrintStream StringBuilder  :     LDC "Writeing: "
00048 Response ByteChunk String String  : PrintStream StringBuilder String  :     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
00049 Response ByteChunk String String  : PrintStream StringBuilder  :     ALOAD 1
00050 Response ByteChunk String String  : PrintStream StringBuilder ByteChunk  :     INVOKEVIRTUAL org/apache/tomcat/util/buf/ByteChunk.toString ()Ljava/lang/String;
00051 Response ByteChunk String String  : PrintStream StringBuilder String  :     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
00052 Response ByteChunk String String  : PrintStream StringBuilder  :     LDC "\n"
00053 Response ByteChunk String String  : PrintStream StringBuilder String  :     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
00054 Response ByteChunk String String  : PrintStream StringBuilder  :     INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
00055 Response ByteChunk String String  : PrintStream String  :     INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
00056 Response ByteChunk String String  :  :     ALOAD 0
00057 Response ByteChunk String String  : Response  :     GETFIELD org/apache/coyote/Response.outputBuffer : Lorg/apache/coyote/OutputBuffer;
00058 Response ByteChunk String String  : OutputBuffer  :     ALOAD 1
00059 Response ByteChunk String String  : OutputBuffer ByteChunk  :     ALOAD 0
00060 Response ByteChunk String String  : OutputBuffer ByteChunk Response  :     INVOKEINTERFACE org/apache/coyote/OutputBuffer.doWrite (Lorg/apache/tomcat/util/buf/ByteChunk;Lorg/apache/coyote/Response;)I
00061 Response ByteChunk String String  : I  :     POP
00062 Response ByteChunk String String  :  :     ALOAD 0
00063 Response ByteChunk String String  : Response  :     DUP
00064 Response ByteChunk String String  : Response Response  :     GETFIELD org/apache/coyote/Response.bytesWritten : J
00065 Response ByteChunk String String  : Response J  :     ALOAD 1
00066 Response ByteChunk String String  : Response J ByteChunk  :     INVOKEVIRTUAL org/apache/tomcat/util/buf/ByteChunk.getLength ()I
00067 Response ByteChunk String String  : Response J I  :     I2L
00068 Response ByteChunk String String  : Response J J  :     LADD
00069 Response ByteChunk String String  : Response J  :     PUTFIELD org/apache/coyote/Response.bytesWritten : J
00070 Response ByteChunk String String  :  :     RETURN
00071 ?        :     NOP
00072 ?        :     NOP
00073 ?        :     NOP
00074 ?        :     NOP
00075 ?        :     NOP
00076 ?        :     NOP
00077 ?        :     NOP
00078 ?        :     NOP
00079 ?        :     NOP
00080 ?        :     NOP
00081 ?        :     NOP
00082 ?        :     NOP
00083 ?        :     NOP
00084 ?        :     NOP
00085 ?        :     NOP
00086 ?        :     NOP
00087 ?        :     NOP
00088 ?        :     NOP
00089 ?        :     NOP
00090 ?        :     NOP
00091 ?        :     NOP
00092 ?        :     NOP
00093 ?        :     NOP
00094 ?        :     NOP
00095 ?        :     NOP
00096 ?        :     NOP
00097 ?        :     ATHROW

I doubt the problem is you can't use ASMIfier on a class which contains an if statement.

It is far more likely that when you added to code generated by the ASMifier, you have used the stack in a way which increased the amount of stack needed and you didn't increase the maximum set at the end of the method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM