0

I am instrumenting some classes and introducing some new local variables. Now, when the user places a breakpoint in the code, and execution is stopped, the newly introduced local variables can be seen inside Intellij IDEA's debugger window. How can I hide them?

UPDATE: I will have to somehow remove debug info from the instrumented code, but not sure how to do it.

UPDATE 2: I am using the ASM library for instrumentation.

 public void visitCode() {
       this.mv.visitLdcInsn(stringToPass);
       this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "MyAgentClass", "loadData", "(Ljava/lang/String;)LDataClass;", false);
       this.mv.visitVarInsn(Opcodes.ASTORE, this.getDataIndex());
}


public void visitMaxs(int maxStack, int maxLocals) {
     if (this.myStartLabel != null && this.myEndLabel != null) {
        this.mv.visitLocalVariable("__my__data__", "Ljava/lang/Object;", (String) null, this.myStartLabel, this.myEndLabel, this.getDataIndex());
     }

       super.visitMaxs(maxStack, maxLocals);
 }

__my__data__ is shown inside Intellij IDEA.

Nfff3
  • 321
  • 8
  • 24
  • Try asking at https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979 See also https://jetbrains.org/intellij/sdk/docs/intro/getting_help.html – Andrey Aug 10 '20 at 12:55
  • 1
    Can you give some more information, why do you need to do this? What's the exact goal you want to accomplish? – bramdc Aug 13 '20 at 16:41
  • My agent runs inside the application and I don't want the end user to see the variables inserted in the app while he/she debugs it. – Nfff3 Aug 13 '20 at 17:03
  • @Nfff3 A [mcve] will help us understand better what you are trying to do. – Code-Apprentice Aug 13 '20 at 17:26
  • Honestly, I think it would be unfair to hide it. It could be possible there is something in the client code that is interacting with your agent. If the client code can run properly without your agent, then perhaps they should do *that* when debugging. – Daniel Aug 15 '20 at 14:42
  • I was quite busy, sorry, added the MRE code. – Nfff3 Aug 16 '20 at 16:35

1 Answers1

1

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.13

Based on the JVM specs, you can remove your local variables from LocalVariableTable. Javassist does that automatically in generated code and I cannot see the variable secretCode during the run:

enter image description here

Decompiling the result class can show that there are no LocalVariableTable entries for it:


  public void run();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: ldc           #39                 // int -889275714
         2: istore_1
         3: iload_1
         4: invokestatic  #43                 // Method org/example/App.test:(I)Ljava/lang/Integer;
         7: astore_2
         8: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
        11: aload_2
        12: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        15: new           #2                  // class SecreFoo
        18: dup
        19: invokespecial #3                  // Method "<init>":()V
        22: astore_1
        23: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
        26: aload_1
        27: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        30: return
      LineNumberTable:
        line 14: 15
        line 15: 23
        line 16: 30
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      31     0  this   LSecreFoo;
           23       8     1 fCopy   LSecreFoo;

So when you are instrumenting your class, drop all your local variables from the table (or do not add them).

Enerccio
  • 257
  • 1
  • 10
  • 23
  • Thank you, I will try to do that. I forgot to say that I'm using ASM, do you have any idea on how to do that in ASM? I added my code to the question. – Nfff3 Aug 16 '20 at 16:35
  • 1
    @Nfff3 in your case I think just drop `this.mv.visitLocalVariable` call. This call is only there to fill that debug info after all. – Enerccio Aug 16 '20 at 16:38
  • wow, this works! But are you sure it won't cause any side effects if I remove it(I tested it and it works but not sure if it will work every time)? I am not really familiar with ASM. – Nfff3 Aug 16 '20 at 18:04
  • it is optional by JLS specification so it really shouldn't. – Enerccio Aug 16 '20 at 21:57
  • just found this: https://stackoverflow.com/questions/28633731/what-does-the-visitlocalvariable-method-of-the-methodvisitor-class-in-the-asm, this explains it – Nfff3 Aug 17 '20 at 14:51
  • Beware: Will not work if user disable debug info generation. Proof: https://blog.jetbrains.com/idea/2013/10/show-local-variables-in-debugger-even-with-no-debug-info/ – user882813 Sep 08 '21 at 23:12