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即可。)
分享到:
相关推荐
这种方式也被称为单表继承或多表继承,是Hibernate支持的四种继承映射策略之一。了解并熟练掌握这种映射模式对于提升Java开发效率和代码维护性至关重要。 在传统的面向对象编程中,类可以有继承关系,但在关系...
在 Java 中,继承是通过使用 `extends` 关键字来实现的,格式为 `public 子类 extends 父类{}`。 继承的优点: 1. 代码重用:继承允许子类继承父类的属性和方法,从而减少代码的冗余和重复。 2. 继承关系建模:...
在Python编程语言中,继承是面向对象编程的一个核心特性,它允许子类(派生类)从父类(基类)那里获得属性和方法,从而实现代码的复用和扩展。这里我们将深入探讨单继承、多继承以及多层继承的概念、语法以及相关...
在Java编程语言中,"在父类获取子类属性"是一个常见的需求,特别是在设计模式、继承和多态性等核心概念的应用中。这个主题涉及到面向对象编程的基本原理,特别是子类继承父类后如何访问和操作子类特有的属性。下面...
UILabel的子类使人联想到和以前的MS-DOS。 安装 手册(阅读:简单) 您可以简单地将DossyText.swift文件添加到您的项目中 CocoaPods(阅读:过度杀伤) 您可以使用安装DossyText将其添加到您的Podfile : pod '...
在Python编程语言中,子类和父类是面向对象编程(OOP)的重要概念,它们构成了继承的基础。继承允许我们创建一个新类(子类),它具有另一个类(父类或基类)的属性和方法,同时还可以添加新的功能或者重写已有功能...
在Python的面向对象编程中,继承是核心概念之一,它允许子类继承父类的特性,包括方法和属性。本课程设计的主题是“子类调用父类同名方法和属性的代码实现”,我们将深入探讨这个主题。 在Python中,子类通过`class...
3. **工厂接口(Factory Method)**:定义创建产品对象的接口,通常是一个抽象类,包含一个或多个工厂方法,用于返回产品对象。 4. **具体工厂(Concrete Factory)**:实现了工厂接口,提供了创建具体产品对象的...
在编程领域,特别是面向对象编程中,"父类赋值给子类" 是一个常见的操作。C# 作为一种强大的面向对象的语言,提供了多种方式来实现这种继承关系下的数据复制。这里我们将深入探讨如何在 C# 中进行父类属性到子类属性...
子类描述装饰器,用于为React创建CSS子类,例如简单的BEM。演示版npm start dev然后访问用法import subClass from 'react-subclass' ;@ subClassclass App extends React . Component { render ( ) { return ( ...
在IT领域,窗口子类化(Window Subclassing)是一种技术,主要用于自定义窗口的行为或外观,例如处理特定的消息或改变窗口的绘制方式。在Windows操作系统中,窗口子类化通常涉及将一个窗口的窗口过程(Window ...
在Java编程语言中,子类继承父类是一种常见的特性,它允许子类扩展或复用父类的功能。当我们创建一个子类对象并将其赋值给父类引用时,这种行为被称为向上转型(Upcasting)。这一过程是自动且安全的,因为子类对象...
例如,我们可以创建一个名为`MyActivity`的子类: ```java public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);...
那只能子类化了 之前有了解过一点点 这次的代码也基本参照的网上的源码 应该还有很多遗漏没写完整的 但是初步使用我觉得差不多 各路大神勿喷。源码里面的代码部分基本上按照我自己的理解带有解释。模块引用了:。1....
标题中的“15 继承(二)(每个子类扩展的属性单独保存在一张表中)”指的是在数据库设计中,特别是在使用对象关系映射(ORM)框架如Hibernate时,处理继承关系的一种策略——单表继承(Single Table Inheritance,STI)...
本压缩包“易语言源码易语言中的Win窗口子类化.rar”主要关注的是易语言在Windows操作系统下的窗口子类化技术。 窗口子类化是Windows编程中一个重要的概念,它允许程序员扩展或修改已有窗口的行为,而无需重新创建...
在Windows编程中,Win32 API提供了一种强大的机制,允许开发者对已存在的窗口进行定制,这就是所谓的“窗口子类化”(Window Subclassing)。窗口子类化是一种技术,通过它,我们可以替换一个窗口的默认消息处理函数...