普通情况下,Btrace脚本有诸多的限制:
can not create new objects. can not create new arrays. can not throw exceptions. can not catch exceptions. can not make arbitrary instance or static method calls - only the public static methods of com.sun.btrace.BTraceUtils class or methods declared in the same program may be called from a BTrace program. (pre 1.2) can not have instance fields and methods. Only static public void returning methods are allowed for a BTrace class. And all fields have to be static. can not assign to static or instance fields of target program's classes and objects. But, BTrace class can assign to it's own static fields ("trace state" can be mutated). can not have outer, inner, nested or local classes. can not have synchronized blocks or synchronized methods. can not have loops (for, while, do..while) can not extend arbitrary class (super class has to be java.lang.Object) can not implement interfaces. can not contains assert statements. can not use class literals.
BTrace的作者这样做也是有安全方面的考虑,不过有些时候,如果能关闭这些限制,BTrace的功能将大大增强。
通过starfish的脚本发现这个限制的开关原理就是com.sun.btrace.unsafe,设置在${BTRACE_HOME}/bin/btrace 中
${JAVA_HOME}/bin/java -Dcom.sun.btrace.probeDescPath=. -Dcom.sun.btrace.dumpClasses=false -Dcom.sun.btrace.debug=false -Dcom.sun.btrace.unsafe=false -cp ${BTRACE_HOME}/build/btrace-client.jar:${TOOLS_JAR}:/usr/share/lib/java/dtrace.jar com.sun.btrace.client.Main $*
一行,
测试如下:
测试程序源代码:
import java.util.Date; /** * created by haitao.yao @ Jun 16, 2011 */ public class TestBtrace { /** * @param args */ public static void main(String[] args) { while(true){ test(new Date()); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void test(Date date){ System.out.println(date); } }
测试btrace脚本:
import java.util.Date; import com.sun.btrace.annotations.BTrace; import com.sun.btrace.annotations.Kind; import com.sun.btrace.annotations.Location; import com.sun.btrace.annotations.OnMethod; /** * created by haitao.yao @ Jun 16, 2011 */ @BTrace public class TestBtrace_Script { @OnMethod(clazz = "TestBtrace", method = "test", location = @Location(value = Kind.RETURN)) public static final void after_test(){ System.out.println("sleep another second @ " + new Date()); try { Thread.sleep(1000); } catch (InterruptedException e) { } } }
启动测试程序,输出如下:
haitao-yao@haitaoyao-laptop:~$ javac TestBtrace.java && java TestBtrace Thu Jun 16 15:18:41 CST 2011 Thu Jun 16 15:18:42 CST 2011 Thu Jun 16 15:18:43 CST 2011
正常情况下启动btrace:
haitao-yao@haitaoyao-laptop:~$ btrace $(jps |grep TestBtrace|cut -d' ' -f 1) TestBtrace_Script.java error: TestBtrace_Script.java:18:method calls are not allowed - only calls to BTraceUtils are allowed error: TestBtrace_Script.java:19:try .. catch .. finally blocks are not allowed BTrace compilation failed
报错,显然不允许调用BTraceUtils以外的方法,修改com.sun.btrace.unsafe为true,再次启动测试:
目标测试程序输出所需结果:
Thu Jun 16 15:22:30 CST 2011 Thu Jun 16 15:22:31 CST 2011 Thu Jun 16 15:22:32 CST 2011 Thu Jun 16 15:22:33 CST 2011 Thu Jun 16 15:22:34 CST 2011 Thu Jun 16 15:22:35 CST 2011 sleep another second @ Thu Jun 16 15:22:35 CST 2011 Thu Jun 16 15:22:37 CST 2011 sleep another second @ Thu Jun 16 15:22:37 CST 2011 Thu Jun 16 15:22:39 CST 2011 sleep another second @ Thu Jun 16 15:22:39 CST 2011
哈哈,done!随便拦截任何目标java程序代码并执行其他代码,功能好强大!
不过线上使用时,还是要小心小心再小心,才可以开启unsafe开关,避免造成事故。
-- EOF --