title: How to add an extra instruction to method in ByteCode using ClassVisitor / Java Bytecode (ASM)
body: <p>I'm writing a gradle plugin for my lib. <a href="https://github.com/shehabic/sherlock" rel="nofollow noreferrer">https://github.com/shehabic/sherlock</a>, I need to inject a network interceptor at compilation time in the byte code of OkHttp Client (<a href="https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/OkHttpClient.java" rel="nofollow noreferrer">https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/OkHttpClient.java</a>)
  to specific I would like to inject the following line in Java:</p>
  
  <pre><code>this.interceptors.add(new com.shehabic.sherlock.interceptors(new SherlockOkHttpInterceptor())
  </code></pre>
  
  <p><a href="https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/OkHttpClient.java#L1068" rel="nofollow noreferrer">https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/OkHttpClient.java#L1068</a></p>
  
  <p>I have written the plugin the transformer already and here's my class writer:</p>
  
  <pre><code>public class SherlockClassWriter {
  
      ClassReader reader;
      ClassWriter writer;
      PublicizeMethodAdapter pubMethAdapter;
      final static String CLASSNAME = "okhttp3.OkHttpClient";
  
      public SherlockClassWriter() {
          try {
              reader = new ClassReader(CLASSNAME);
              writer = new ClassWriter(reader, 0);
          } catch (IOException ex) {
              ex.printStackTrace();
          }
      }
  
      public SherlockClassWriter(byte[] contents) {
          reader = new ClassReader(contents);
          writer = new ClassWriter(reader, 0);
      }
  
      public static void main(String[] args) {
          SherlockClassWriter ccw = new SherlockClassWriter();
          ccw.publicizeMethod();
      }
  
      public byte[] publicizeMethod() {
          pubMethAdapter = new PublicizeMethodAdapter(writer);
          reader.accept(pubMethAdapter, 0);
          return writer.toByteArray();
      }
  
      public class PublicizeMethodAdapter extends ClassVisitor {
  
          TraceClassVisitor tracer;
          PrintWriter pw = new PrintWriter(System.out);
  
          public PublicizeMethodAdapter(ClassVisitor cv) {
              super(ASM4, cv);
              this.cv = cv;
              tracer = new TraceClassVisitor(cv, pw);
          }
  
          @Override
          public MethodVisitor visitMethod(
              int access,
              String name,
              String desc,
              String signature,
              String[] exceptions
          ) {
              if (name.equals("build")) {
                  MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
                  // call method in java:
                  // this.interceptors.add(new com.shehabic.sherlock.interceptors(new SherlockOkHttpInterceptor())
              }
              return tracer.visitMethod(access, name, desc, signature, exceptions);
          }
      }
  }
  </code></pre>
  
  <p>a similar method that adds interceptors has a bytecode as follows:</p>
  
  <pre><code>aload_0
  getfield #4 &lt;okhttp3/OkHttpClient$Builder.interceptors&gt;
  aload_1
  invokeinterface #117 &lt;java/util/List.add&gt; count 2
  pop
  aload_0
  </code></pre>
  
  <p><em>My questions are:</em>
  1.How do I inject more code into a method? even if Bytecode.</p>
  
  <p><em>Update</em>
  Here is my working solution, based on the answer:
  <a href="https://github.com/shehabic/sherlock/blob/creating-plugin-to-intercept-all-okhttp-connections/sherlock-plugin/src/main/java/com/shehabic/sherlock/plugin/SherlockClassWriter.java" rel="nofollow noreferrer">https://github.com/shehabic/sherlock/blob/creating-plugin-to-intercept-all-okhttp-connections/sherlock-plugin/src/main/java/com/shehabic/sherlock/plugin/SherlockClassWriter.java</a></p>