-
1. Re: Cannot invoke method of parameter objects $1, $2,....
adinn Nov 8, 2010 2:00 PM (in response to trungsi)Hi,
It'snice to see that you are trying to use Byteman.
duc trung tran wrote:
I have a rule like this :RULE a_rule
CLASS MyClass
METHOD myMethod(Object)
IF TRUE
DO traceln("invoke method on parameter " + $1.otherMethod())
ENDRULEThe parameter object ($1) is alwyas of type OtherClass (which has otherMethod method) at runtime. But i have a error message "Cannot invoke otherMethod of java.lang.Object..."
Is this a bug or not implemented feature?
Could you please provide the definition of your method? Does the method declaration specify that the parametr is of type Obejct or OtherClass?
In this rule the method appears to have one argument of type Object. So, when Byteman tries to typecheck the rule it can only assume that $1 is an instance of Object. When it sees the call $1.otherMethod() it will only typecheck the rule if the declared type, Object, has a method called otherMethod. Obviously this fails so the rule is not type correct. This is just the same as when javac compiles java code. Like javac, Byteman performs strict type checking.
Of course, when the rule gets executed $1 may actually be an instance of OtherClass. But Byteman has to be able to type check the rule using the declared argument type not the type found at execute-time when the rule fired. If it used the execute-time type then it would have to type check the rule every time it was triggered and this would make the rule engine much slower. It would also make it impossible to compile the rule code to bytecode.
-
2. Re: Cannot invoke method of parameter objects $1, $2,....
trungsi Nov 8, 2010 2:51 PM (in response to adinn)Hi,
Thanks for your rapid and detailed answer. It's really a cool tool Byteman .
I tried to cast $1 to OtherClass in the BIND clause but it does not work either. I have to implement custom helper for that?
On the other hand, i would like to know if it's possible to capture private nested class or static initialization?
Thanks
-
3. Re: Cannot invoke method of parameter objects $1, $2,....
adinn Nov 8, 2010 3:33 PM (in response to trungsi)duc trung tran wrote:
Thanks for your rapid and detailed answer. It's really a cool tool Byteman .
Thanks very much.
duc trung tran wrote:
I tried to cast $1 to OtherClass in the BIND clause but it does not work either. I have to implement custom helper for that?
I have been thinking about adding casting to rules. It's a little tricky but it is possible. One of the hardest tasks is to get my rule garmmar to parse casts and not treat them as parse errors -- I know that sounds silly but it is actually really tricky to do it and also retain good error reporting. So far most people have been able to use Byteman fairly effectively without using casts but I would be interested to see some good use cases which would justify adding it to the language.
Yes, you are right that it is possibekl to add your own helper class to do the cast. For example, you could define the following helper:
package org.my; import org.jboss.byteman.rule.helper.Helper; import org.other.OtherClass; public Class MyHelper extends Helper { public OtherClass asOtherClass(Object object) { if (object instanceof OtherClass) { return (OtherClass) object; } return null; }
Then your rule could be redefined as follows
RULE a_rule CLASS MyClass METHOD myMethod(Object) HELPER org.my.MyHelper BIND otherClassObject = asOtherClass($1) IF TRUE DO traceln("invoke method on parameter " + otherClassObject.otherMethod()) ENDRULE
duc trung tran wrote:
On the other hand, i would like to know if it's possible to capture private nested class or static initialization?
If you want to attach a rule to a method fo a nested class then you need to refer to the nested class usiing the internal JVM name format whihc uses a $ as rthe separator between the outer class and the inner class name
RULE b_rule
CLASS MyClass$NestedClassMETHOD myOtherMethod(Object)
. . .It is also possible to attach rules to classinitialiser methods using the internal name for a class initializer method, <clinit> e.g.
RULE c_rule
CLASS SomeClassMETHOD <clinit>
. . .However, in order to make this work you need to be sure that you install the rule before SomeClass is loaded. If you install the rule after SomeClassis loaded then the <clinit> method will already have run and your rule will not get called. The best way to achieve this is to install the rule on the JVM command line i.e. if the rule is contained in a script file /path/to/myrules.txt then run your code using the bmjava script in theinstall bindirectory as follows:
bmjava.sh -s /path/to/myrules.txt -classpath <myclasspath> org.my.MyMainClass
If you cannot use bmjava.sh and have to run using the java command directly then you need to pass the script using the javaagent oiption to the java command e.g.
java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=script:/path/to/myrules.txt \ -classpath <myclasspath> org.my.MyMainClass