This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Can we obtain return value of Java methods?
- From: Tetsuo Handa <penguin-kernel at I-love dot SAKURA dot ne dot jp>
- To: systemtap at sourceware dot org
- Date: Thu, 13 Apr 2017 01:11:42 +0900
- Subject: Can we obtain return value of Java methods?
- Authentication-results: sourceware.org; auth=none
Hello.
I'd like to obtain return value of Java methods, but currently $return
variable is not usable inside java().class().method().return probes.
Since byteman accepts $! as an variable for return value of Java methods,
I guess we can implement it by mapping $return variable inside
java().class().method().return probes into $! variable.
A manually operated demonstration is shown below.
Step 1: Create Class1.java like below and compile it.
---------- Class1.java ----------
public class Class1 {
public static int intfunc(int a)
{
return a + a;
}
public static String strfunc(String a)
{
return "Hello " + a;
}
public static Class1 objfunc(Class1 a)
{
return a;
}
public static void main(String[] args) throws Exception
{
while (true) {
Thread.sleep(5000);
intfunc(100);
strfunc("world");
objfunc(new Class1());
}
}
}
---------- Class1.java ----------
Step 2: Run Java probes which prints arguments.
----------------------------------------
# SYSTEMTAP_VERBOSE=1 stap -m class1 -e 'probe java("Class1").class("Class1").method("intfunc(int)").return { println("int = " . arg1); }
probe java("Class1").class("Class1").method("strfunc(String)").return { println("str = " . arg1); }
probe java("Class1").class("Class1").method("objfunc(Class1)").return { println("obj = " . arg1); }' -c 'java -cp . Class1'
----------------------------------------
Output looks like below.
----------------------------------------
/usr/local/libexec/systemtap/stapbm: line 160: netstat: command not found
java -classpath /usr/share/java/byteman/byteman-install.jar:/usr/share/java/byteman/byteman.jar:/usr/lib/jvm/java/lib/tools.jar:/usr/local/libexec/systemtap/HelperSDT.jar org.jboss.byteman.agent.install.Install -b -p 11161 -Dorg.jboss.byteman.transform.all=true -Dorg.jboss.byteman.verbose 35778
byteman jar is /usr/share/java/byteman/byteman.jar
Setting org.jboss.byteman.transform.all=true
Setting org.jboss.byteman.verbose=
TransformListener() : accepting requests on localhost:11161
Byteman agent installed for java pid 35778, port 11161
Byteman agent reused for java pid 35778, port 11161
Byteman rule file:
RULE class1probe_3577
CLASS Class1
METHOD intfunc(int)
HELPER org.systemtap.byteman.helper.HelperSDT
AT RETURN
IF TRUE
DO METHOD_STAP31_PROBE1("class1probe_3577", $1)
ENDRULE
java -classpath /usr/share/java/byteman/byteman-submit.jar:/usr/share/java/byteman/byteman.jar:/usr/local/libexec/systemtap/HelperSDT.jar org.jboss.byteman.agent.submit.Submit -p 11161 -l /root/.systemtap/java/localhost.localdomain-35853.btm
Byteman rule file:
Byteman agent reused for java pid 35778, port 11161
RULE class1probe_3579
CLASS Class1
METHOD objfunc(Class1)
HELPER org.systemtap.byteman.helper.HelperSDT
AT RETURN
IF TRUE
DO METHOD_STAP31_PROBE1("class1probe_3579", $1)
ENDRULE
java -classpath /usr/share/java/byteman/byteman-submit.jar:/usr/share/java/byteman/byteman.jar:/usr/local/libexec/systemtap/HelperSDT.jar org.jboss.byteman.agent.submit.Submit -p 11161 -l /root/.systemtap/java/localhost.localdomain-35856.btm
Byteman rule file:
RULE class1probe_3578
CLASS Class1
METHOD strfunc(String)
HELPER org.systemtap.byteman.helper.HelperSDT
AT RETURN
IF TRUE
DO METHOD_STAP31_PROBE1("class1probe_3578", $1)
ENDRULE
java -classpath /usr/share/java/byteman/byteman-submit.jar:/usr/share/java/byteman/byteman.jar:/usr/local/libexec/systemtap/HelperSDT.jar org.jboss.byteman.agent.submit.Submit -p 11161 -l /root/.systemtap/java/localhost.localdomain-35877.btm
TransformListener() : handling connection on port 11161
retransforming Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3577 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.intfunc(int) int for rule class1probe_3577
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3577 in class Class1
TransformListener() : handling connection on port 11161
install rule class1probe_3577
retransforming Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3577 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.intfunc(int) int for rule class1probe_3577
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3577 in class Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3579 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.objfunc(Class1) Class1 for rule class1probe_3579
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3579 in class Class1
TransformListener() : handling connection on port 11161
install rule class1probe_3579
retransforming Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3577 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.intfunc(int) int for rule class1probe_3577
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3577 in class Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3579 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.objfunc(Class1) Class1 for rule class1probe_3579
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3579 in class Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3578 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.strfunc(java.lang.String) java.lang.String for rule class1probe_3578
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3578 in class Class1
install rule class1probe_3578
Rule.execute called for class1probe_3577_3
HelperManager.install for helper classorg.systemtap.byteman.helper.HelperSDT
class1probe_3577 execute()
Rule.execute called for class1probe_3578_5
HelperManager.install for helper classorg.systemtap.byteman.helper.HelperSDT
class1probe_3578 execute()
Rule.execute called for class1probe_3579_4
HelperManager.install for helper classorg.systemtap.byteman.helper.HelperSDT
class1probe_3579 execute()
int = 100
str = world
obj = Class1@28cc6a8
Rule.execute called for class1probe_3577_3
class1probe_3577 execute()
Rule.execute called for class1probe_3578_5
class1probe_3578 execute()
Rule.execute called for class1probe_3579_4
class1probe_3579 execute()
int = 100
str = world
obj = Class1@684640e6
----------------------------------------
Step 3: Copy the contents of byteman rule files, with $1 replaced with $!
and save the result as /tmp/class1.btm .
---------- /tmp/class1.btm ----------
RULE class1probe_3577_2
CLASS Class1
METHOD intfunc(int)
HELPER org.systemtap.byteman.helper.HelperSDT
AT RETURN
IF TRUE
DO METHOD_STAP31_PROBE1("class1probe_3577", $!)
ENDRULE
RULE class1probe_3578_2
CLASS Class1
METHOD strfunc(String)
HELPER org.systemtap.byteman.helper.HelperSDT
AT RETURN
IF TRUE
DO METHOD_STAP31_PROBE1("class1probe_3578", $!)
ENDRULE
RULE class1probe_3579_2
CLASS Class1
METHOD objfunc(Class1)
HELPER org.systemtap.byteman.helper.HelperSDT
AT RETURN
IF TRUE
DO METHOD_STAP31_PROBE1("class1probe_3579", $!)
ENDRULE
---------- /tmp/class1.btm ----------
Step 4: Load /tmp/class1.btm into running java proess.
----------------------------------------
java -classpath /usr/share/java/byteman/byteman-submit.jar:/usr/share/java/byteman/byteman.jar:/usr/local/libexec/systemtap/HelperSDT.jar org.jboss.byteman.agent.submit.Submit -p 11161 -l /tmp/class1.btm
----------------------------------------
Output looks like below.
----------------------------------------
TransformListener() : handling connection on port 11161
retransforming Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3577 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.intfunc(int) int for rule class1probe_3577
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3577 in class Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3579 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.objfunc(Class1) Class1 for rule class1probe_3579
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3579 in class Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3578 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.strfunc(java.lang.String) java.lang.String for rule class1probe_3578
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3578 in class Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3577_2 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.intfunc(int) int for rule class1probe_3577_2
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3577_2 in class Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3578_2 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.strfunc(java.lang.String) java.lang.String for rule class1probe_3578_2
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3578_2 in class Class1
org.jboss.byteman.agent.Transformer : possible trigger for rule class1probe_3579_2 in class Class1
RuleTriggerMethodAdapter.injectTriggerPoint : inserting trigger into Class1.objfunc(Class1) Class1 for rule class1probe_3579_2
org.jboss.byteman.agent.Transformer : inserted trigger for class1probe_3579_2 in class Class1
Rule.execute called for class1probe_3577_6
HelperManager.install for helper classorg.systemtap.byteman.helper.HelperSDT
class1probe_3577 execute()
Rule.execute called for class1probe_3577_2_9
HelperManager.install for helper classorg.systemtap.byteman.helper.HelperSDT
class1probe_3577_2 execute()
Rule.execute called for class1probe_3578_8
HelperManager.install for helper classorg.systemtap.byteman.helper.HelperSDT
class1probe_3578 execute()
Rule.execute called for class1probe_3578_2_10
HelperManager.install for helper classorg.systemtap.byteman.helper.HelperSDT
class1probe_3578_2 execute()
Rule.execute called for class1probe_3579_7
HelperManager.install for helper classorg.systemtap.byteman.helper.HelperSDT
class1probe_3579 execute()
Rule.execute called for class1probe_3579_2_11
HelperManager.install for helper classorg.systemtap.byteman.helper.HelperSDT
class1probe_3579_2 execute()
int = 100
int = 200
str = world
str = Hello world
obj = Class1@5578cce2
obj = Class1@5578cce2
^CWARNING: Child process exited with status 130
WARNING: /usr/local/bin/staprun exited with status: 1
Pass 5: run failed. [man error::pass5]
----------------------------------------