-
1. Re: Does rule condition support null checking?
adinn Feb 28, 2012 10:45 AM (in response to ant_db)Hi Anton,
Anton Ryabtsev wrote:
Is it possible to create rule that should does actions only if some variable is not null?
So the rule like this:
RULE rule
CLASS Foo
METHOD bar
AT EXIT
IF $! != null
DO traceln("yes, it is possible!")
ENDRULE
Yes, it is possible. In fact, the example above probably ought to work. However, you may find that in some cases when you supply null as a literal in your rule code the type checker is unable to identify a type for the literal at the point of mention and so rejects your rule with a type error.
Initially this was very broken. Now it should only be rare cases where the type checker cannto handle a mention of null. There is still an outstanding JIRA for these remaining cases.
Do you have a specific reason for asking? For example, have you found a case which Byteman cannot handle? If so I'll be happy to look at it and see if it is possible to fix Byteman to deal with it or else to rewrite your rule to work round this limitation.
-
2. Re: Does rule condition support null checking?
ant_db Feb 29, 2012 1:40 AM (in response to adinn)Hi Andrew,
If I try to apply the above rule to the next class
{code}
public class Foo {
public String bar(int input) {
if ( input == 0 ) {
return null;
}
return "bar";
}
}
{code}
I get this exception:
org.jboss.byteman.rule.exception.TypeException: NullLiteral.typeCheck : unable to derive type for null from context
at org.jboss.byteman.rule.expression.NullLiteral.typeCheck(NullLiteral.java:68)
at org.jboss.byteman.rule.expression.ComparisonExpression.typeCheck(ComparisonExpression.java:53)
-
3. Re: Does rule condition support null checking?
ant_db Feb 29, 2012 4:27 AM (in response to adinn)I believe it is a different issue, but I can't use the above rule if my class looks like as the following:
{code}
public class Foo {
public void bar() {
synchronized ( this ) {
for ( int i = 0; i < 10; i++ ) {
System.out.println(i);
}
}
}
}
{code}
In this example the exception is like this:
java.lang.NullPointerException
at org.jboss.byteman.agent.adapter.cfg.CFG.computeContainment(CFG.java:1108)
at org.jboss.byteman.agent.adapter.cfg.CFG.carryForward(CFG.java:962)
at org.jboss.byteman.agent.adapter.cfg.CFG.split(CFG.java:1240)
at org.jboss.byteman.agent.adapter.RuleTriggerMethodAdapter.visitJumpInsn(RuleTriggerMethodAdapter.java:776)
at org.jboss.byteman.agent.adapter.EntryTriggerAdapter$EntryTriggerMethodAdapter.visitJumpInsn(EntryTriggerAdapter.java:176)
at org.jboss.byteman.objectweb.asm.tree.JumpInsnNode.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.tree.InsnList.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.tree.MethodNode.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.commons.JSRInlinerAdapter.visitEnd(Unknown Source)
at org.jboss.byteman.objectweb.asm.ClassReader.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.ClassReader.accept(Unknown Source)
at org.jboss.byteman.agent.Transformer.transform(Transformer.java:746)
at org.jboss.byteman.test.TestScript.checkRules(TestScript.java:266)
at org.jboss.byteman.test.TestScript.testScript(TestScript.java:139)
at org.jboss.byteman.test.TestScript.main(TestScript.java:98)
-
4. Re: Does rule condition support null checking?
adinn Feb 29, 2012 4:42 AM (in response to ant_db)HI Anton,
Your rule does indeed fail to typecheck which is not what I expected. I thought the changes I made to partially resolve BYTEMAN-86 had dealt with this case but clearly there is more work needed. Anyway, this fairly simple variant of your rule works ok.
RULE rule
CLASS Bar
METHOD bar
AT EXIT
BIND nullStr : String = null
IF $! != nullStr
DO traceln("yes, it is possible!")
ENDRULE
In this version the declaration of local variable nullStr with type String provides the type checker with an expected type for the null literal used to initialize the variable.
-
5. Re: Does rule condition support null checking?
adinn Feb 29, 2012 4:44 AM (in response to ant_db)Anton Ryabtsev wrote:
at org.jboss.byteman.agent.adapter.cfg.CFG.computeContainment(CFG.java:1108)
at org.jboss.byteman.agent.adapter.cfg.CFG.carryForward(CFG.java:962)
at org.jboss.byteman.agent.adapter.cfg.CFG.split(CFG.java:1240)
at org.jboss.byteman.agent.adapter.RuleTriggerMethodAdapter.visitJumpInsn(RuleTriggerMethodAdapter.java:776)
at org.jboss.byteman.agent.adapter.EntryTriggerAdapter$EntryTriggerMethodAdapter.visitJumpInsn(EntryTriggerAdapter.java:176)
at org.jboss.byteman.objectweb.asm.tree.JumpInsnNode.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.tree.InsnList.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.tree.MethodNode.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.commons.JSRInlinerAdapter.visitEnd(Unknown Source)
at org.jboss.byteman.objectweb.asm.ClassReader.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.ClassReader.accept(Unknown Source)
at org.jboss.byteman.agent.Transformer.transform(Transformer.java:746)
at org.jboss.byteman.test.TestScript.checkRules(TestScript.java:266)
at org.jboss.byteman.test.TestScript.testScript(TestScript.java:139)
at org.jboss.byteman.test.TestScript.main(TestScript.java:98)
Ooh, that's exciting! I'll take a look at this and see if I can find out what is causing the exception. Can you confirm what version of Byteman you are using?
-
6. Re: Does rule condition support null checking?
ant_db Feb 29, 2012 5:09 AM (in response to adinn)Thanks for your help, Andrew.
Byteman version: 2.0.0
-
7. Re: Does rule condition support null checking?
adinn Feb 29, 2012 6:09 AM (in response to ant_db)Hi Anton,
Anton Ryabtsev wrote:
Thanks for your help, Andrew.
Byteman version: 2.0.0
That's rather strange. When I ran bmcheck on your class and rule I did not get this null pointer exception. I just got the typecheck error you posted earlier.
I would very much like to find out what is going on here as there is obviously something wrong but I don't really know what
Are the code and rule script which gave this exception exactly as you specified in the earlier notes?
Can you provide the sequence of commands you ran to generate the error?
Also, what is the OS and JVM you are using?
Thanks for any info you can provide
-
8. Re: Does rule condition support null checking?
adinn Feb 29, 2012 6:28 AM (in response to ant_db)Ah,ok, I think that was my mistake. I am now getting an exception but not the one you are seeing. I get this
[adinn@sputstik byteman]$ bmcheck -cp src foo.btm
checking rule rule
ERROR : Unexpected exception transforming class Foo using rule "rule" loaded from foo.btm line 5
java.lang.NullPointerException
at org.jboss.byteman.objectweb.asm.Frame.a(Unknown Source)
at org.jboss.byteman.objectweb.asm.MethodWriter.visitVarInsn(Unknown Source)
at org.jboss.byteman.objectweb.asm.MethodAdapter.visitVarInsn(Unknown Source)
at org.jboss.byteman.agent.adapter.RuleGeneratorAdapter.visitVarInsn(RuleGeneratorAdapter.java:1425)
at org.jboss.byteman.agent.adapter.RuleTriggerMethodAdapter.visitVarInsn(RuleTriggerMethodAdapter.java:713)
at org.jboss.byteman.agent.adapter.RuleGeneratorAdapter.storeLocal(RuleGeneratorAdapter.java:1493)
at org.jboss.byteman.agent.adapter.RuleTriggerMethodAdapter.doReturnOrThrowSave(RuleTriggerMethodAdapter.java:297)
at org.jboss.byteman.agent.adapter.RuleTriggerMethodAdapter.injectTriggerPoint(RuleTriggerMethodAdapter.java:1102)
at org.jboss.byteman.agent.adapter.ExitTriggerAdapter$ExitTriggerMethodAdapter.visitInsn(ExitTriggerAdapter.java:79)
at org.jboss.byteman.objectweb.asm.tree.InsnNode.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.tree.InsnList.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.tree.MethodNode.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.commons.JSRInlinerAdapter.visitEnd(Unknown Source)
at org.jboss.byteman.objectweb.asm.ClassReader.accept(Unknown Source)
at org.jboss.byteman.objectweb.asm.ClassReader.accept(Unknown Source)
at org.jboss.byteman.agent.Transformer.transform(Transformer.java:746)
at org.jboss.byteman.test.TestScript.checkRules(TestScript.java:266)
at org.jboss.byteman.test.TestScript.testScript(TestScript.java:139)
at org.jboss.byteman.test.TestScript.main(TestScript.java:98)
TestScript: 1 total errors
0 total warnings
0 parse errors
0 type errors
0 type warnings
The error above is happening because your rule mentions variable $! but the method you are injecting into has return type void. What should happen is that the initial check to see whether the candidate method is a valid target for the rule should notice that you are using $! and realise that this is invalid. Insteda it goes on to inject the trigger code into the target method and tries to create a local var slot to save the return value on the stack. This breaks because i) there is no return value on the stack and ii) it is trying to create a local var slot with type void. So, I need to fix the trigger injecton code to inlcude this preliminary check. I will raise a JIRA for this and psot a reference on this thread (I also probably need to do the same for AFTER CALL rules where $! refers to the return value form the called method).
That said, I don't know why you are seeing a different exception trace. So, details of how you got there would be very welcome.
-
9. Re: Does rule condition support null checking?
ant_db Feb 29, 2012 6:44 AM (in response to adinn)Well, I use next rule to produce this exciting thing(sorry for misleading you):
RULE rule
CLASS Foo
METHOD bar
AT ENTRY
IF true
DO traceln("yes, it works!")
ENDRULE
OS: WinXP
JVM: Sun jdk_1.6.0_21
-
10. Re: Does rule condition support null checking?
adinn Feb 29, 2012 9:13 AM (in response to ant_db)Hi Anton,
Anton Ryabtsev wrote:
Well, I use next rule to produce this exciting thing(sorry for misleading you):
RULE rule
CLASS Foo
METHOD bar
AT ENTRY
IF true
DO traceln("yes, it works!")
ENDRULE
OS: WinXP
JVM: Sun jdk_1.6.0_21
Hmm, that's interestingh. When I run this on Linux it works without any exception. I will try it on XP when I get a chance (my XP machine is at home) and let you know what happens.
-
11. Re: Does rule condition support null checking?
adinn Feb 29, 2012 9:20 AM (in response to ant_db)Could you help me by posting the output when you run the following command
javap -c -verbose -private -classpath XXX Foo
where you need to substitute the path to Foo.class in place of XXX (or omit -classpath XXX if your class file is in the working directory)
It looks like the problem is happening during scanning of the bytecode when a jump instruction is reached so seeing the bytecode might be very useful
-
12. Re: Does rule condition support null checking?
ant_db Feb 29, 2012 9:48 AM (in response to adinn)Attached
-
fooBC.txt.zip 1.4 KB
-
-
13. Re: Does rule condition support null checking?
adinn Feb 29, 2012 11:04 AM (in response to ant_db)Oooh, it gets even more exciting!! Can you tell me what bytecode compiler (i.e. javac program) was used to generate your class file? It looks (maybe?) like the code the Jikes compiler generates. Anyway, Byteman is going to barf on this sort of code because of the way the loop code is generated. There is nothing wrong with your file as bytecode -- it is perfectly legitimate. The problem belongs to Byteman's code analyzer (class CFG whihc you can see in the stacktrace) .
If you (or anyone else reading this thread) want to understand the details then here goes. Otherwise close your eyes now.
Byteman expects that the first entry to every basic block of code occurs either via a drop through or a forward jump in other words primary control flow follows bytecode order. Of course, if there is a for or while loop in a method then the bytecode will have to (re-)enter a block via a backward jump but Byteman expects the first instructions in the loop condition and loop body to be arrived at via a forward transfer of control. This assumption may be invalid for your javac compiler but it is necessary because Byteman needs to push constraints through the code as it traverses the instruction sequence.
In this specific case the constraint is that there is a monitorenter before the loop body (this is the opening half of how synchronized is implemented) and it means that any path out of the loop needs to include a monitorexit (the other half of how syncrhonized is implemented) which Byteman can pair up with its corresponding monitorenter.
Now, with the code generated by OpenJDK's javac the loop condition comes at the top of the loop and skips over the body if it is false. The body directly follows after the condition and there is an unconditional jump backwards at the end of the loop to retest the condition.
public void bar();
Code:
Stack=2, Locals=4, Args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: iconst_0
5: istore_2
6: iload_2
7: bipush 10
9: if_icmpge 25
12: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
15: iload_2
16: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
19: iinc 2, 1
22: goto 6
25: aload_1
26: monitorexit
27: goto 35
30: astore_3
31: aload_1
32: monitorexit
33: aload_3
34: athrow
35: return
You can see the loop condition being entered at offest 6 (iload_2 loads the loop counter which is compared against constant value 10) and the loop body entered at offset 12.
Unfortunately with the bytecode you provided the loop condition is at the bottom of the loop starting at offset 19. The loop body starts at offset 9 and is skipped over at loop start by a forward jump at offset 6. The loop condition ends with a conditional jump back to the start of the loop in place of the unconditional jump we saw before.
public void bar();
Code:
Stack=2, Locals=3, Args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: iconst_0
5: istore_2
6: goto 19
9: getstatic #15; //Field java/lang/System.out:Ljava/io/PrintStream;
12: iload_2
13: invokevirtual #21; //Method java/io/PrintStream.println:(I)V
16: iinc 2, 1
19: iload_2
20: bipush 10
22: if_icmplt 9
25: aload_1
26: monitorexit
27: goto 33
30: aload_1
31: monitorexit
32: athrow
33: return
So, when Byteman sees the goto at instruction 6 it can propagate the monitorenter constraint to the end of the loop body but but it does not yet know that the loop body code starting at offset 9 is also reachable from the monitorenter. So, when Byteman analyzes this body code it does not know that a monitorenter will have happened before this block is reached. So, when it gets to the monitorexit in the block starting at instruction 25 it has lost track of the corresponding monitorenter. The null pointer is supposed to be a reference to instruction 3 only there is no such reference.
Ok, you can open your eyes now :-)
I'll raise another JIRA for this but I cannot see it getting fixed very soon. This assumption is deep in the heart of the Byteman code generation strategy and is key to why Byteman can transform code relatively quickly. Anyway, thanks for reporting the problem and providing all the info needed to identify where things are going wrong.
regards,
Andrew Dinn
-
14. Re: Does rule condition support null checking?
ant_db Feb 29, 2012 11:17 AM (in response to adinn)I use Eclipse to generate it. So guess, it is ECJ.
Thanks for quick reply.