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

BTrace二三事之二:OnMethod子类匹配BUG(怀疑)

    博客分类:
  • java
阅读更多
BTRace1.2.2版本
@OnMethod(clazz = "+my.Command", method="execute")
对子类的匹配(怀疑)存在BUG。

即:加载Agent之前的已载入的Class被拦截了,但Agent加载之后的Class没有拦截。

从源代码看应该是这样,涉及到子类匹配检查的主要两个变量:

hasSubclassChecks :是否需要检查子类匹配,如果需要的话,
所有通过ClassLoader.defineClass()加载的类,会被注入一段静态初始化代码:
{
  BTraceRuntime.retransform(Ljava/lang/String;Ljava/lang/Class;)
}

作用是,在类被初始化后,立即触发类的重转换。

第二个变量是:skipRetransforms:是否跳过类的重转换,
当Agent加载后,如果已经存在部分类发生了转换,那么这个变量会被设置为true,
从而导致后续类没有被拦截。

BTraceHost:
public interface Command {
	void execute();
}

public class Foo1Command implements Command {
public void execute() {
	System.out.println("foo1 command execute...");
}
}

public class Foo2Command implements Command {
public void execute() {
	System.out.println("foo2 command execute...");
}
}

public class HostMain {
public static void main(String[] args) {
	System.out.println("pid = " + getSelfPID());
	new Thread(new Spy()).start();
}
static String getSelfPID() {
	String pname = ManagementFactory.getRuntimeMXBean().getName();
	int index = pname.indexOf('@');
	if (index == -1) {
		throw new RuntimeException("获取自身进程PID失败!进程名称为:" + pname);
	}
	String pid = pname.substring(0, index);
	return pid;
}
}

public class Spy implements Runnable {
static Map<String, String> commands = new HashMap<String, String>();
static {
	commands.put("1", "my.Foo1Command");
	commands.put("2", "my.Foo2Command");
}

public void run() {
	try {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("enter Command: ");
		System.out.println("commands : " + commands);
		System.out.println("请验证下面两个场景:");
		System.out.println("场景一:加载Foo1;加载Agent;加载Foo2---结果:Foo1被拦截;Foo2未拦截");
		System.out.println("场景二:加载Agent;          加载Foo2---结果:Foo1被拦截;Foo2被拦截");
		for (String line; (line = in.readLine()) != null;) {
			doAction(line);
		}
	}
	catch (Exception e) {
		e.printStackTrace();
	}
}

void doAction(String action) throws Exception {
	String commandName = commands.get(action);
	if (commandName != null) {
		Command command = (Command) Class.forName(commandName).newInstance();
		command.execute();
	}
	else {
		System.out.println("invalid command..");
		System.out.println("commands : " + commands);
	}
}
}


BTraceClient:
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 });
}
}

@BTrace(unsafe = true)
public class SampleScript {
@OnMethod(clazz = "+my.Command", method = "execute", location = @Location(Kind.RETURN))
public static void onExecuteReturn(@ProbeClassName String className, @Duration long duration) {
	BTraceUtils.println(Strings.concat("execute return : className = ", className));
}
}


附件一:BTrace1.2.2 执行库下载;
附件二:BTrace1.2.2 源代码下载;
附件三:验证的例子;(直接运行例子中的BTraceHost和BTraceClient即可。)
1
0
分享到:
评论

相关推荐

    Hibernate继承映射二:每个子类一张表

    这种方式也被称为单表继承或多表继承,是Hibernate支持的四种继承映射策略之一。了解并熟练掌握这种映射模式对于提升Java开发效率和代码维护性至关重要。 在传统的面向对象编程中,类可以有继承关系,但在关系...

    java 类的继承 基础理解

    在 Java 中,继承是通过使用 `extends` 关键字来实现的,格式为 `public 子类 extends 父类{}`。 继承的优点: 1. 代码重用:继承允许子类继承父类的属性和方法,从而减少代码的冗余和重复。 2. 继承关系建模:...

    第十二天 04单继承:子类只继承一个父类【千锋Python人工智能学院】1

    在Python编程语言中,继承是面向对象编程的一个核心特性,它允许子类(派生类)从父类(基类)那里获得属性和方法,从而实现代码的复用和扩展。这里我们将深入探讨单继承、多继承以及多层继承的概念、语法以及相关...

    在父类获取子类属性

    在Java编程语言中,"在父类获取子类属性"是一个常见的需求,特别是在设计模式、继承和多态性等核心概念的应用中。这个主题涉及到面向对象编程的基本原理,特别是子类继承父类后如何访问和操作子类特有的属性。下面...

    Python子类父类知识学习

    在Python编程语言中,子类和父类是面向对象编程(OOP)的重要概念,它们构成了继承的基础。继承允许我们创建一个新类(子类),它具有另一个类(父类或基类)的属性和方法,同时还可以添加新的功能或者重写已有功能...

    python课程设计-26-子类调用父类同名方法和属性之代码实现.ev4.rar

    在Python的面向对象编程中,继承是核心概念之一,它允许子类继承父类的特性,包括方法和属性。本课程设计的主题是“子类调用父类同名方法和属性的代码实现”,我们将深入探讨这个主题。 在Python中,子类通过`class...

    C#面向对象设计模式纵横谈(5):Factory Method 工厂方法模式(创建型模式)

    3. **工厂接口(Factory Method)**:定义创建产品对象的接口,通常是一个抽象类,包含一个或多个工厂方法,用于返回产品对象。 4. **具体工厂(Concrete Factory)**:实现了工厂接口,提供了创建具体产品对象的...

    父类赋值给子类

    在编程领域,特别是面向对象编程中,"父类赋值给子类" 是一个常见的操作。C# 作为一种强大的面向对象的语言,提供了多种方式来实现这种继承关系下的数据复制。这里我们将深入探讨如何在 C# 中进行父类属性到子类属性...

    react-subclass:React CSS子类

    子类描述装饰器,用于为React创建CSS子类,例如简单的BEM。演示版npm start dev然后访问用法import subClass from 'react-subclass' ;@ subClassclass App extends React . Component { render ( ) { return ( ...

    易语言窗口子类化例程源码

    在IT领域,窗口子类化(Window Subclassing)是一种技术,主要用于自定义窗口的行为或外观,例如处理特定的消息或改变窗口的绘制方式。在Windows操作系统中,窗口子类化通常涉及将一个窗口的窗口过程(Window ...

    java 子类对象赋值给父类对象的使用

    在Java编程语言中,子类继承父类是一种常见的特性,它允许子类扩展或复用父类的功能。当我们创建一个子类对象并将其赋值给父类引用时,这种行为被称为向上转型(Upcasting)。这一过程是自动且安全的,因为子类对象...

    Android学习之路——5.Activity子类

    例如,我们可以创建一个名为`MyActivity`的子类: ```java public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);...

    易语言组件美化例程 窗口子类化 子类化选择列表框

    那只能子类化了 之前有了解过一点点 这次的代码也基本参照的网上的源码 应该还有很多遗漏没写完整的 但是初步使用我觉得差不多 各路大神勿喷。源码里面的代码部分基本上按照我自己的理解带有解释。模块引用了:。1....

    15 继承(二)(每个子类扩展的属性单独保存在一张表中)

    标题中的“15 继承(二)(每个子类扩展的属性单独保存在一张表中)”指的是在数据库设计中,特别是在使用对象关系映射(ORM)框架如Hibernate时,处理继承关系的一种策略——单表继承(Single Table Inheritance,STI)...

    易语言源码易语言中的Win窗口子类化.rar

    本压缩包“易语言源码易语言中的Win窗口子类化.rar”主要关注的是易语言在Windows操作系统下的窗口子类化技术。 窗口子类化是Windows编程中一个重要的概念,它允许程序员扩展或修改已有窗口的行为,而无需重新创建...

    解说Win32的窗口子类代码示例

    在Windows编程中,Win32 API提供了一种强大的机制,允许开发者对已存在的窗口进行定制,这就是所谓的“窗口子类化”(Window Subclassing)。窗口子类化是一种技术,通过它,我们可以替换一个窗口的默认消息处理函数...

    基对象引用子类实例(C# 形象说明:父母可以代表孩子做很多事情)

    多态性是OOP(面向对象编程)的三大基本特征之一,另外两个是封装和继承。在这个主题中,我们将深入探讨如何在C#中使用基对象引用子类实例,以及它在实际开发中的应用。 首先,让我们理解什么是基类(Base Class)...

Global site tag (gtag.js) - Google Analytics