2011-10-07 4 views
1

ASM 3.3.1을 사용하고 있습니다. 클래스를 가로 채고 메소드 중 하나를 변경하려고합니다. org.objectweb.asm.util.ASMifierClassVisitor를 사용하여 ASM 코드를 가져와 새 메소드를 만듭니다. 모든 것은 훌륭하게 작동하지만 if() 문을 저주합니다. 결과 asm 코드를 if 문 (또는 루프)과 함께 사용하려고하면 런타임에 "스택 크기가 너무 큼"오류가 발생합니다. ClassWriter writer = new ClassWriter (ClassWriter.COMPUTE_FRAMES);를 사용하고 있습니다. 이것이 나에게주는 ASMIFY 코드입니다.Java 바이트 코드 ASM을 사용한 조작

if() 문을 ASMIFYING 할 때 오류가 발생하는 이유는 무엇입니까? 나는 어떤 도움을 크게 크게 감사 할 것입니다.

`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 ASMifying. (참고 : 나는 방법을 찍은 그게 내가 사용하고 전부로)

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(); 
    } 

원래 메소드는 마지막 두 줄

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

이 잘 보이지 않는이 포함되어 있습니다. CheckClassAdapter.verify() 메소드를 사용하여 클래스의 일부분을 처리했습니다.

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 
+0

작성중인 비 ASM 코드를 게시 할 수 있습니까? 그런 식으로 당신의 의도를 더 쉽게 읽을 수 있다면, 당신이 만드는 ASM이 왜 스택과 논쟁을하고 있는지 알아낼 수 있습니다. –

+0

좋아, 나는 ASMifying 코드를 업데이트했다. – Chris

+0

(개인적으로 저는이 모든 것을 손으로 건너 뛰고 AspectJ를 사용하지 않을 것입니다.) –

답변

0

나는 문제가 당신이 if 문을 포함하는 클래스에 ASMIfier 사용할 수 없습니다 의심.

ASMifier에 의해 생성 된 코드에 추가 할 때 필요한 스택의 양을 늘리고 메소드의 끝 부분에서 최대 집합을 증가시키지 않은 방식으로 스택을 사용했을 가능성이 훨씬 더 높습니다 .

+0

안녕하세요, 응답 해 주셔서 감사합니다. 사실 나는 ASMifier 코드에 추가하지 않았다. 나는 내가 원했던 완전히 새로운 방법을 ASM 화했다. 해당 코드에 if 문이 있으면 오류가 발생합니다. 그것들이 없으면 다른 모든 ASMified 코드는 훌륭하게 작동합니다. – Chris

+0

이런 식으로 실패한 Java 코드의 예를 들려 줄 수 있습니까? ASM은 JDK의 모든 클래스에서 테스트됩니다. –

+0

물론, 나는 ASMifying하는 방법을 게시했습니다. 나는 if 문을 사용할 것이다. 그러나 지금은 그냥 쓰레기 b/c를 인쇄하고있다. 하지만 If 문을 꺼내면 클래스의 ASMifying 및 인터셉트 및 메서드 교체가 훌륭하게 작동합니다. – Chris

관련 문제