raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.23k stars 804 forks source link

I am sorry, this is a question about java bytecode #1580

Closed jiangyunpeng closed 8 months ago

jiangyunpeng commented 8 months ago

I am sorry, this is a question about java Bytecode not about byteBuddy, because i couldn't find a appropriate place to post. and i know the Rafael Winterhalter is a nice guy. so i post here🙇 .

This question is about LocalVariableTable scope.

I write a simple code:

L11    public void sum2() {
L12        int a = 25;
L13        try {
L14            int b = 8;
L15            if (a > 20) {
L16                int k = a + b;
L17                System.out.println("k=" + k);
L18            }
L19        } catch (Exception e) {
L20            e.printStackTrace();
L21        }
L22    }

I think the scope of variable b must be in the try statement, which is line 15~18.

But actually, when i use javap generate bytecode :

  Exception table:
     from    to  target type
         3    41    44   Class java/lang/Exception
  LineNumberTable:
    line 12: 0
    line 14: 3
    line 15: 6
    line 16: 12
    line 17: 16
    line 21: 41
    line 19: 44
    line 20: 45
    line 22: 49
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
       16      25     3     k   I
        6      35     2     b   I
       45       4     2     e   Ljava/lang/Exception;
        0      50     0  this   Lcom/buzz/asm/util/Sum;
        3      47     1     a   I
  StackMapTable: number_of_entries = 3
    frame_type = 252 /* append */
      offset_delta = 41
      locals = [ int ]
    frame_type = 66 /* same_locals_1_stack_item */
      stack = [ class java/lang/Exception ]
    frame_type = 4 /* same */

The scope of variable b is line 15~21? (start=6,end=41) ,Why? It is obvious,the variable b can't be accessed in the catch statement.

i asked chatGPT, it said:

In Java, variable scoping is determined by the block structure, but the Java compiler might choose to allocate storage for local variables in a broader scope than their actual usage. This behavior is allowed by the Java Language Specification (JLS), and it's up to the compiler's implementation to decide how to manage the local variables.

but i can't confirm it if correct, because i don't find any references describe it

raphw commented 8 months ago

ChatGTP is pretty much correct. There's no need to limit the scope here as the assignment can never yield an exception. I assume that it's a simple simplification.

jiangyunpeng commented 8 months ago

Thanks a lot for the detailed response.

Actually, i used ByteBuddy and asm to develop a online debug tools.

I decompile user's class to java source code, and user can debug at any source code line. We will record every variable before user debug code line . for example below code ,if user debug at L15, we will record the value of 'a' and 'b' variables.

L11    public void sum2() {
L12        int a = 25;
L13        try {
L14            int b = 8;
L15            if (a > 20) {
L16                int k = a + b;
L17                System.out.println("k=" + k);
L18            }
L19        } catch (Exception e) {
L20            e.printStackTrace();
L21        }
L22    }

But if user debug at L20. we will generate error bytecode base ' LocalVariableTable ' , Because our bytecode will try to record variable 'b' at catch statement but actually it can't be accessed.

So could you give some advice to me for this case?

jiangyunpeng commented 8 months ago

i think may be need parse source code manually for resolve this case

raphw commented 8 months ago

I would argue that it would be possible to access the value using the Java debugger.

jiangyunpeng commented 8 months ago

Thanks , Have a nice day.