1 Reply Latest reply on Oct 27, 2011 5:16 AM by Andrew Dinn

    about sun jvm can't use local var

    swimablefish Newbie

      hi , I've read about this problem,  https://issues.jboss.org/browse/BYTEMAN-28 . We use sun's jvm, that means we can't use this function.

      Is it possible that byteman provide a array which contain's local var, then we can according to the order of the local var showed in method to

      get the local var. So we can get rid of  the dependence on the jvm.  I don't know whether this solutions is feasible.

        • 1. Re: about sun jvm can't use local var
          Andrew Dinn Master

          Hi swimable,

          swimablefish wrote:

           

          hi , I've read about this problem,  https://issues.jboss.org/browse/BYTEMAN-28 . We use sun's jvm, that means we can't use this function.

          Is it possible that byteman provide a array which contain's local var, then we can according to the order of the local var showed in method to

          get the local var. So we can get rid of  the dependence on the jvm.  I don't know whether this solutions is feasible.

          Yes, it would be possible to provide some sort of anonymous indexed syntax for accessing local variables in the same way as for parameter variables. So, for example, given a method like this

           

          class MapUtils

          {

            . . .

            public long cityBlockMetric(Point p1, Point p2)

            {

              int x1 = p1.x;

              int x2 = p2.x;

              int y1 = p1.y;

              int y2 = p2.y;

              long result = 0;
              if (x1 < x2) {

                int xDiff = (x2 - x1);

                result += xDiff;

              } else {

                int xDiff = (x1 - x2);

                result += xDiff;

              }

              if (y1 < y2) {

                int yDiff = (y2 - y1);

                result += yDiff;

              } else {

                int yDiff = (y1 - y2);

                result += yDiff;

              }   

            }

            return result;

          }

           

          You could use a trace rule like this to trace each fo the asisgnments to result

           

          RULE trace metric

          CLASS MapUtils

          METHOD cityBlockMetric

          AFTER WRITE $local5 ALL

          IF TRUE

          DO traceln("added " + $local6 + " to result " $local5)

          ENDRULE

           

          This rule would match the four assignments inside the if/else clauses because there are 6 local variables present at those points so the references to $local5 and $local6 clearly make sense. However, it would fail to match the initial assignment of result because the reference to $local6 would not be able to be resolved. At each of the four matching trigger locations  $local5 can be clearly identified as the local variable result of type long and $local6 as an int local variable -- either xDiff or yDiff.

           

          If instead you were to use an array $locals[] then and you wodl have to refer to the locals vars as follows.

           

          RULE trace metric

          CLASS MapUtils

          METHOD cityBlockMetric

          AFTER WRITE $locals[5] ALL

          IF TRUE

          DO traceln("added " + $locals[6] + " to result " $locals[5])

          ENDRULE

           

          Two problems occur here. First you could only safely typecheck the array as an Object[]. This means $locals[5] would have to be typed as an Object. That would not matter much in this rule because the value is only used in the call to traceln but it would matter if you actually wanted to use $locals[5] as a long or $locals[6] as an int. For that to work you would need some way of casting it to a long (I am thinking about a solution to hwo to cast values in rules but that's another rather long story)

           

          The second problem is that this rule would match the initial assignment where locals only has length 5. So the reference to $locals[6] in the action will result in an array bounds exception. To make this work correctly you woudl need to add a condition which would stop the rule firing at the first trigger location

           

          RULE trace metric

          CLASS MapUtils

          METHOD cityBlockMetric

          AFTER WRITE $locals[5] ALL

          IF $locals.length <= 5

          DO traceln("added " + $locals[6] + " to result " $locals[5])

          ENDRULE


          So if anything were to be implemented then I think the first version is preferable.

           

          I don't see this as being very difficult to add. I need to think more about how to refer to the local vars. Using $local1 etc is an option but it means references to local variables whose name really is local1, etc will then be misinterpreted. But thta's a small detail. My only real concern is that this feature is perhaps difficult to use. In order to write your rule you  need to be able to keep track of how many local variables are in scope at each injection point. This is hard enough when you have a single injection point but when  you use an ALL count for the location you may find that $local4 has a different type at different matching locatons.The result will be that you get typecheck errors for some locations while the rule is happily injected at others. That outcome is also posisbel but far less less likely when using actual local variable names because values with different types usually have different names, meanign that the rule wil fail to match rather than fail to typecheck.

           

          Anyway, I think it is defiitely worth considering further the idea of providing this feature. So, thank you very much for the suggestion. I will raise a feature request JIRA for htis and add a link to this thread.