I have used net.bytebuddy.asm.Advice to add code before and after suitably annotated methods, to start and stop timers. The modified classes are manually loaded into the target class loader before their originals can be referenced, thereby supplanting them. I'm using OSGi (Equinox).

Pretty sweet but when I stop the Eclipse (Photon 4.8.0) debugger on a breakpoint in the target method, the Variables view shows only: 

> 
> com.sun.jdi.InternalException: Got error code in reply:35 occurred
>  retrieving 'this' from stack frame.
> 
> 
> 

Is this inevitable and unavoidable? Kinda ruins my use-case if this renders instrumented code undebuggable :(

(I have disabled the option "Show method result after a step operation (if supported by the VM; may be slow".)

Example
-------

I believe I may have found some issues with the generated bytecode.

Class to be instrumented:

```
 1 package com.tom.test;
 2
 3 import com.tom.instrument.Instrumented;
 4 import com.tom.instrument.Timed;
 5
 6 @Instrumented(serviceType = "blah")
 7 public class Test {
 8
 9 @Timed
10 public void writeName() {
11   final String myLocal = "Tom";
12      System.out.println(myLocal);  
13   }
14
15 }

```

"Advice":

```
package com.tom.instrument;

import net.bytebuddy.asm.Advice.OnMethodEnter;

public class Instrumentation {

    @OnMethodEnter
    public static void onMethodEnter() {
        System.out.println("Enter");
    }

}

```

Call to Byte Buddy:

```
new ByteBuddy()
    .redefine(type, ClassFileLocator.ForClassLoader.of(this.classLoader))
    .visit(Advice.to(Instrumentation.class)
    .on(isAnnotatedWith(Timed.class)))
    .make().saveIn(new File("instrumented"));

```

Result in javap:

```
Compiled from "Test.java"
...

  public void writeName();
    Code:
       0: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #40                 // String Enter
       5: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: goto          11
      11: ldc           #17                 // String Tom
      13: astore_1
      14: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream;
      17: ldc           #17                 // String Tom
      19: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      22: return
    LineNumberTable:
      line 11: 0
      line 12: 14
      line 13: 22
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
         11      12     0  this   Lcom/tom/test/Test;
         14       9     1 myLocal   Ljava/lang/String;
}

```

If I set a break point on line 11 of Test.java then the Eclipse Debug view says: `<unknown receiving type>(Test).writeName() line: 11`

And the Variables view says: `com.sun.jdi.InternalException: Got error code in reply:35 occurred retrieving 'this' from stack frame.`

If I hack the bytecode changing 00 to 0B at 0x2A2 so the line number table looks like:

```
LineNumberTable:
  line 11: 11
  line 12: 14
  line 13: 22

```

Then everything is fine! And that kinda seems correct to me but I'm no expert here.

If I also use `@OnMethodExit` too then it's a bit more complicated. Add the following to `Instrumentation.class`:

```
@OnMethodExit
public static void onMethodExit() {
    System.out.println("Exit");
}

```

javap gives:

```
Compiled from "Test.java"
...

  public void writeName();
    Code:
       0: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #40                 // String Enter
       5: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: goto          11
      11: aload_0
      12: astore_1
      13: ldc           #17                 // String Tom
      15: astore_2
      16: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream;
      19: ldc           #17                 // String Tom
      21: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      24: goto          27
      27: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream;
      30: ldc           #42                 // String Exit
      32: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      35: goto          38
      38: return
    LineNumberTable:
      line 11: 0
      line 12: 16
      line 13: 24
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
         13      14     1  this   Lcom/tom/test/Test;
         16      11     2 myLocal   Ljava/lang/String;
}

```

To fix this I have to update the line number table and the local variable table. Like this:

```
LineNumberTable:
  line 11: 13
  line 12: 16
  line 13: 24
LocalVariableTable:
  Start  Length  Slot  Name   Signature
     13      14     0  this   Lcom/tom/test/Test;
     16      11     1 myLocal   Ljava/lang/String;

```

Diff:
[![enter image description here](https://i.stack.imgur.com/Ea4EY.png)](https://i.stack.imgur.com/Ea4EY.png)

Maybe it's a bug the the Eclipse debugger expects `this` to always be in slot 0? Or maybe that's the way it should be. The error code 35 comes from the JVM though.

The reason why adding the exit advice changes the slots seem to be because it causes `ForInstrumentedMethod.Default.Copying` to be used instead of `Simple`. And they have different implementations of `variable()`.