`
sswh
  • 浏览: 161650 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

BTrace二三事之四:unsafe脚本需要注意的

    博客分类:
  • java
阅读更多

unsafe脚本怎样才是安全的??除了脚本对已有对象应该限于只读操作,
并且不应该持有对象的引用外,暂时所能想到的,先列几条吧:

1、启用unsafe模式:
   修改BTrace启动参数 -Dcom.sun.btrace.unsafe=true
   BTrace脚本注解:@BTrace(unsafe = true)

2、BTrace脚本类的ClassLoader为引导类加载器;
   被跟踪的类的加载器仍为原类加载器不变;
   agent在加载脚本类之前会对脚本类进行修改,
   包括修改脚本方法名称、@TLS变量修改为ThreadLocal等;

3、BTrace脚本编译后,@OnMethod、@OnError等注解的方法,
   将被添加到目标类中。而脚本中的公共调用方法,仍保留在脚本中。
   所以,被注解的方法中可以引用目标类加载器可见的类型;
   但脚本的公共调用方法中,只能引用引导类加载器可见的类型,
   否则运行期报NoClassDefFoundError

4、进入方法为location = @Location(Kind.ENTER)
   退出方法的途径有2个:
   正常退出:location = @Location(Kind.RETURN)
   异常退出:location = @Location(Kind.ERROR)

5、可以用-Dcom.sun.btrace.dumpClasses=true
   -Dcom.sun.btrace.dumpDir=./yourDumpDir方式将修改后的类转储,
   借助反编译工具查看增强后的代码;

6、BTrace1.2.2版本的BUG:
   @OnMethod(clazz = "+my.Command", method = "execute")
   如果agent附加到目标进程时,已经加载过“+”对应的子类,
   那么只有已加载的子类会被修改,之后加载的子类不会被脚本代码所修改;
  
@BTrace(unsafe = true)
public class SampleScript {

	@TLS
	// 在转换后的Script脚本类中,@TLS变量会自动声明为ThreadLocal变量
	static Object fooParam;

	@OnMethod(clazz = "/my\\..*?Command/", method = "execute", type = "void(my.FooParam)")
	public static void onExecute(@ProbeClassName
	String className, AnyType fooParam) {
		SampleScript.fooParam = fooParam;
	}

	@OnMethod(clazz = "/my\\..*?Command/", method = "execute", location = @Location(Kind.RETURN), type = "void(my.FooParam)")
	public static void onExecuteReturn(@ProbeClassName
	String className) {
		BTraceUtils.println("execute return : className = " + className);
		BTraceUtils.println("param : fooParam = " + fooParam);
		// 这儿引用Foo1Command不会有问题
		Foo1Command command = new Foo1Command();
		System.out.println(command.toString());
		// 在test()引用Foo1Command将抛出NoClassDefFoundError
		test();
	}

	@OnMethod(clazz = "/my\\..*?Command/", method = "execute", location = @Location(Kind.ERROR), type = "void(my.FooParam)")
	public static void onExecuteError(@ProbeClassName
	String className, Throwable e) {
		BTraceUtils.println("execute error : className = " + className);
		BTraceUtils.println("param : fooParam = " + fooParam);
		BTraceUtils.println("throw : message = " + e.getMessage());
	}

	public static void test() {
		System.out.println("test...");
		// 将抛出NoClassDefFoundError
		Foo1Command command = new Foo1Command();
		System.out.println(command.toString());
	}
}


public class BTraceStarter {

	public static void main(String[] args) throws Exception {

		String classpath = System.getProperty("java.class.path");
		if (!classpath.contains("tools.jar")) {
			throw new RuntimeException("请在类路径中设置tools.jar!");
		}

		System.setProperty("com.sun.btrace.probeDescPath", ".");
		System.setProperty("com.sun.btrace.dumpClasses", "true");
		System.setProperty("com.sun.btrace.dumpDir", "./dump");
		System.setProperty("com.sun.btrace.debug", "false");
		System.setProperty("com.sun.btrace.unsafe", "true");

		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入目标进程PID: ");
		String pid = in.readLine();

		String script = new File(BTraceStarter.class.getResource("SampleScript.class").getFile()).getCanonicalPath();
		com.sun.btrace.client.Main.main(new String[] { pid, script });
	}
}
1
0
分享到:
评论
1 楼 xwqiang 2015-04-08  
我执行这个脚本有异常:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(Unknown Source)
at com.sun.btrace.client.Client.attach(Client.java:224)
at com.sun.btrace.client.Main.main(Main.java:156)
at my.app.test.BTraceStarter.main(BTraceStarter.java:35)

也就是执行com.sun.btrace.client.Main.main(new String[] { pid, script });
的时候异常。
方法中pid script都有且script文件存在,请问是怎么回事。谢过!

相关推荐

Global site tag (gtag.js) - Google Analytics