2 Replies Latest reply on Dec 7, 2016 9:07 AM by abof

    Differences in behavior for boolean / Boolean in method local variable assigning

    abof

      Hi!

      I have question about differences in "Byteman" behavior for boolean / Boolean local method variable assigning. A little example:

       

      public class IffedLogic {
      
        public static enum Branch {
          FIRST_BRANCH,
          SECOND_BRANCH,
          DEFAULT_BRANCH;
        }
      
        public Branch branchMe(int aArg) {
          Boolean shouldEnterBranch = false; // <-- Wrapper class
          
          shouldEnterBranch = aArg > 100;
          if (shouldEnterBranch) {
            return Branch.FIRST_BRANCH;
          }
          
          shouldEnterBranch = aArg > 300;
          if (shouldEnterBranch) {
            return Branch.SECOND_BRANCH;
          }
      
          return Branch.DEFAULT_BRANCH;
        }
      
      }
      

       

      Basically - branchMe method determines result by testing aArg value against some hardcoded numbers. Easy peasy.

       

      Now; consider rule:

       

      RULE messWithBranch
      CLASS IffedLogic
      METHOD branchMe
      AT READ $shouldEnterBranch ALL
      IF TRUE
      DO 
        traceln("[LOG] Replacing shouldEnterBranch = " +  $shouldEnterBranch);
        $shouldEnterBranch=true;
      ENDRULE
      

       

      In jUnit tests of branchMe method I have, for test purposes, injected the rule above and... as expected no mather what - shouldEnterBranch - is always true when it's using in if instructions. That's not suprising...

       

      Surprising is that: when I change shouldEnterBranch type from Boolean wrapper to primitive - boolean - suddenly I get:

       

      java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number
       at bmunit.IffedLogic.branchMe(IffedLogic.java:9)
       at bmunit.IffedLogicTest.defABranchTest(IffedLogicTest.java:30)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
       at java.lang.reflect.Method.invoke(Method.java:497)
       at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
       at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
       at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
       at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
       at org.jboss.byteman.contrib.bmunit.BMUnitRunner$6.evaluate(BMUnitRunner.java:241)
       at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
       at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
       at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
       at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
       at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
       at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
       at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
       at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
       at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
       at org.jboss.byteman.contrib.bmunit.BMUnitRunner$2.evaluate(BMUnitRunner.java:104)
       at org.jboss.byteman.contrib.bmunit.BMUnitRunner$1.evaluate(BMUnitRunner.java:75)
       at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
       at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
       at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
      

       

      In addition in logs I can see that primitive boolean has, under the hood (in bytecode), numeric value:

      ...
      [LOG] Replacing shoulEnterBranch = 1
      ...
      [LOG] Replacing shoulEnterBranch = 0
      ...
      

       

      I would love to find out why is that so and, if it's possible, how achieve same results as with Boolean type of shouldEnterBranch.

       

      Best regards!