Consider a class StaticStepOver, which is a part of the attached project.
To reproduce, unzip StaticStepOver.zip and debug the StaticStepOver class via jdb in following steps:
1) Run the app in one terminal:
$ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:57047 -classpath StaticStepOver/build/classes staticstepover.StaticStepOver
2) Attach jdb:
$ jdb -attach localhost:57047
Then step through the execution:
main[1] step
>
Step completed: "thread=main", staticstepover.StaticStepOver.main(), line=33 bci=0
main[1] step
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.maxPerYear(), line=27 bci=0
You see that the static initializer was executed, but step did not enter it.
Even if I put a breakpoint into the static initializer code, subsequent steps ignore the static block and suspend execution in the instance code. To reproduce, run the application again (1) and attach jdb again (2) and follow these steps:
main[1] stop at staticstepover.StaticStepOver:33
main[1] stop at staticstepover.StaticStepOver$MyEnum:21
main[1] run
> Set deferred breakpoint staticstepover.StaticStepOver:33
Breakpoint hit: "thread=main", staticstepover.StaticStepOver.main(), line=33 bci=0
main[1] step
Breakpoint hit: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=21 bci=26
main[1] step
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.maxPerYear(), line=27 bci=0
Regardless of the last step being "step" or "next", it can be seen, that after the execution was stopped on the breakpoint in the static block, the following step goes through the entire block and suspends in the code outside the block. This is definitely a bug.
The trigger of the faulty behavior seems to be the first step. When we do similar steps again, but do "cont" instead of the first "step", it works as expected:
Run the application again (1) and attach jdb again (2) and follow these steps:
main[1] stop at staticstepover.StaticStepOver:33
main[1] stop at staticstepover.StaticStepOver$MyEnum:21
main[1] run
> Set deferred breakpoint staticstepover.StaticStepOver:33
Breakpoint hit: "thread=main", staticstepover.StaticStepOver.main(), line=33 bci=0
main[1] cont
> Set deferred breakpoint staticstepover.StaticStepOver$MyEnum:21
Breakpoint hit: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=21 bci=26
main[1] next
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=22 bci=34
main[1] next
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=23 bci=42
main[1] next
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=24 bci=50
main[1] next
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.maxPerYear(), line=27 bci=0
Can be reproduced in both JDK 1.7.0 and JDK 1.8.0
To reproduce, unzip StaticStepOver.zip and debug the StaticStepOver class via jdb in following steps:
1) Run the app in one terminal:
$ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:57047 -classpath StaticStepOver/build/classes staticstepover.StaticStepOver
2) Attach jdb:
$ jdb -attach localhost:57047
Then step through the execution:
main[1] step
>
Step completed: "thread=main", staticstepover.StaticStepOver.main(), line=33 bci=0
main[1] step
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.maxPerYear(), line=27 bci=0
You see that the static initializer was executed, but step did not enter it.
Even if I put a breakpoint into the static initializer code, subsequent steps ignore the static block and suspend execution in the instance code. To reproduce, run the application again (1) and attach jdb again (2) and follow these steps:
main[1] stop at staticstepover.StaticStepOver:33
main[1] stop at staticstepover.StaticStepOver$MyEnum:21
main[1] run
> Set deferred breakpoint staticstepover.StaticStepOver:33
Breakpoint hit: "thread=main", staticstepover.StaticStepOver.main(), line=33 bci=0
main[1] step
Breakpoint hit: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=21 bci=26
main[1] step
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.maxPerYear(), line=27 bci=0
Regardless of the last step being "step" or "next", it can be seen, that after the execution was stopped on the breakpoint in the static block, the following step goes through the entire block and suspends in the code outside the block. This is definitely a bug.
The trigger of the faulty behavior seems to be the first step. When we do similar steps again, but do "cont" instead of the first "step", it works as expected:
Run the application again (1) and attach jdb again (2) and follow these steps:
main[1] stop at staticstepover.StaticStepOver:33
main[1] stop at staticstepover.StaticStepOver$MyEnum:21
main[1] run
> Set deferred breakpoint staticstepover.StaticStepOver:33
Breakpoint hit: "thread=main", staticstepover.StaticStepOver.main(), line=33 bci=0
main[1] cont
> Set deferred breakpoint staticstepover.StaticStepOver$MyEnum:21
Breakpoint hit: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=21 bci=26
main[1] next
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=22 bci=34
main[1] next
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=23 bci=42
main[1] next
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.<clinit>(), line=24 bci=50
main[1] next
>
Step completed: "thread=main", staticstepover.StaticStepOver$MyEnum.maxPerYear(), line=27 bci=0
Can be reproduced in both JDK 1.7.0 and JDK 1.8.0