3 Replies Latest reply on Apr 27, 2012 5:42 AM by adinn

    Accessing a variable scoped to a switch case block, within an action expression

    jaikiran

      Assuming I have code which looks like:

       

      public void doSomething() {
             .....
            switch(onsomething) {
                     case 1:
                          int someVar = ....;
                          fooBar(); // assume this is line 10
                          break;
                     default:
                          break;
           }  
      }
      

       

      Assuming the line number for fooBar() invocation is 10 and I want to check the value of someVar, I've got this rule:

      RULE test
      CLASS someClass
      METHOD doSomething
      AT LINE 10
      IF TRUE
      DO
      
      System.out.println("Value is = " +  $someVar);
      
      ENDRULE
      

       

      This rule keeps failing with a message along the lines of "unsatisfiable local variable binding $someVar checking method doSomething". My guess is that it has to do with the fact that the someVar is scoped within the swith case block and isn't visible outside of it. But since I am trying to insert this rule at LINE 10 where this variable is infact visible, shouldn't this rule pass? Or is there some different way to write this rule?

       

      Am using 2.0.1 version by the way.

        • 1. Re: Accessing a variable scoped to a switch case block, within an action expression
          adinn

          Hi Jaikiran

          jaikiran pai wrote:

           

           

          This rule keeps failing with a message along the lines of "unsatisfiable local variable binding $someVar checking method doSomething". My guess is that it has to do with the fact that the someVar is scoped within the swith case block and isn't visible outside of it. But since I am trying to insert this rule at LINE 10 where this variable is infact visible, shouldn't this rule pass? Or is there some different way to write this rule?

           

          Hmm, I may to investigate this one too. Byteman uses the localvar debug info installed by javac to identify in-scope variables. So, if there is an bytecode range where the debugger thinks the variable is in scope then byteman also ought to think the variable is in scope. So, I'll ask the obvious question first: are you sure you compiled this class with the relevant debug options to include both line numbers and local var tables (obviously '-g' is enough).

           

          Assuming the answer is yes then the immediate thing to do is to disassemble the class using javap -c (-private) -verbose and see which bytecodes are included in the scope of line 10 and whether the local var is visible in that scope. n.b. with location AT LINE 10 the injection point is just before the first bytecode labelled with line number = 10 -- except of course for constructors where injection can sometimes be delayed until after a super or indirect this constructor has been called.

           

          One thing to note is that in the byetcode variables go out of scope once they are no longer referenced. I say this because it raises an issue with the (possibly artificial) example you provided

           

          switch(onsomething) {
            case 1:
              int someVar = ....;
              fooBar(); // assume this is line 10
              break;

           

          variable somevar is  actually out of scope at line 10. I know in theory Java says the variable is available from the declaration point onwards but of course, that is a moot point if subsequent code does not reference it. javac  can (and will) choose to limit the localvars extent to the bytecode section where it is live and in use. In practice, with this example javac would limit the scope of someVar up to (but not to overlap) the call to foobar. Now a scope also starts immediately after the related local var slot is written. As a consequence the start and end bytecode offsets for the scope are the same for this example and hence the scope has an extent of length zero.

          • 2. Re: Accessing a variable scoped to a switch case block, within an action expression
            jaikiran

            Andrew, sorry about the late reply. I've been delaying on replying to this thread, hoping to get to the bottom of this issue. But other priority tasks aren't letting that happen. FWIW, I haven't been able to reproduce this against a simple class/method. However, I keep seeing this against a specific class/method that belongs to jboss-remoting project. So I'll have to spend a bit more time to see what's going on there. I'll come back to this soon.

             

             

            Andrew Dinn wrote:

             

             

            One thing to note is that in the byetcode variables go out of scope once they are no longer referenced. I say this because it raises an issue with the (possibly artificial) example you provided

             

            switch(onsomething) {
              case 1:
                int someVar = ....;
                fooBar(); // assume this is line 10
                break;

             

            variable somevar is  actually out of scope at line 10. I know in theory Java says the variable is available from the declaration point onwards but of course, that is a moot point if subsequent code does not reference it. javac  can (and will) choose to limit the localvars extent to the bytecode section where it is live and in use. In practice, with this example javac would limit the scope of someVar up to (but not to overlap) the call to foobar. Now a scope also starts immediately after the related local var slot is written. As a consequence the start and end bytecode offsets for the scope are the same for this example and hence the scope has an extent of length zero.

            Yes, the code I posted was artificial and the real code actually references that variable in the subsequent line(s). But thank you for explaining what javac does in cases like in the above (artificial) code. I had a feeling that javac would be smart enough to do such a thing, but I wasn't ever sure about it. Thanks for confirming it.

            • 3. Re: Accessing a variable scoped to a switch case block, within an action expression
              adinn

              Hi Jaikiran,

              jaikiran pai wrote:

               

              Andrew, sorry about the late reply. I've been delaying on replying to this thread, hoping to get to the bottom of this issue. But other priority tasks aren't letting that happen. FWIW, I haven't been able to reproduce this against a simple class/method. However, I keep seeing this against a specific class/method that belongs to jboss-remoting project. So I'll have to spend a bit more time to see what's going on there. I'll come back to this soon.

               

              No apology needed. I have been feeling guilty myself about not trying to reproduce this -- I am very busy on JVM work at present.

               

              Can you point me at the offending bytecode and the relevant injection point. I could at least decompile it and see what the local var table says.

               

              Also, if you can either run bmcheck yourself and see if the injection fails or advise me of which jars I need to provide in order to be able to check the rule using bmcheck then we can see if we get an inject failure at check time. That should make it very easy to debug the injection problem.

               

              n.b. bmcheck needs enough jars in the classpath to resolve references when it loads the target class. Often the jar containing the target class is enough but sometimes it needs extra jars to resolve classes imported from other packages. You make these available on the command line using -cp

               

                bmcheck -cp jar1 . . . -cp jarN path/to/myscript.btm