Differences in behavior for boolean / Boolean in method local variable assigning
abof Dec 7, 2016 5:32 AMHi!
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!