Java 应用程序探针管理器
Java™ 探测器管理器 (JPM) 支持以与 C 和 C++ 探测器管理器相同的方式探测 Java 应用程序。 单个 Vue 脚本应该可以通过使用不同的 JVM 进程标识,同时跟踪多个 java 应用程序。 可以使用相同的脚本来探测 syscalls 或 C/C++ 应用程序以及 Java 应用程序,并且可以使用其他探测器管理器。
类似于 uft(用户函数跟踪)探针管理器,java 探针管理器还接受以下格式的 5 元组调查规范:
uftjava :< process_ID> :*:< _qualified_function_name >: entry
其中第二个元组是对应于要跟踪的 Java 应用程序的 JVM 进程的进程标识。
第三个字段:保留以供以后使用。
第四个字段:其中,需要指定 java 方法。
此名称是如 java 应用程序中使用的完整名称,如 Mypackage.Myclass.Mymethod。
可能应用的部分限制是
- 只能调查纯 java 方法,不能跟踪 Native(共享库调用)或已加密的代码。
- 只支持入口调查。
- 只能支持 JVM v1.5 和更高版本(支持 JVMTI 接口)。
- 在任何给定的时间点,没有两个 Probevue 会话可以使用 @@uftjava探测同一个 Java 应用程序。
- 不支持多形/过载方法。
- 不支持跟踪/访问外部变量使用与任何 Probevue 关键字或内置名称相同的名称。 这可能需要重命名那些外部符号 (Java 应用程序变量名称)。
- 此发行版中不支持访问 java 应用程序数组。
- 此发行版中不支持访问 java 应用程序数组。
- 此发行版中不支持 java 语言的 get_function () 内置。
注: 在跟踪非静态方法的情况下,自变量编号以 __arg2 开头,如 C++ 的非静态方法。 __arg1 用于自引用 (此指针)。
数据访问:java 调查的操作块可以访问类似于现有行为的以下数据。
- 操作块可以访问全局、局部和核心脚本变量。
- 操作块可以访问原语类型的方法参数(入口类变量)。
- 操作块可以访问内置变量。
- 操作块可以通过标准名称 (仅静态 (类成员)) 访问 Java 应用程序变量。
x = some_package.app.class.var_x; //Access static/class member.
- 支持访问 java 应用程序原语类型变量;必须隐式转换/提升/转换它们,而不丢失 Vue 语言中等效类型的任何值。 但实际内存使用情况 (大小) 可能与 Java 语言不同。
下表列出了 Java 探针管理器上下文中支持的函数:
函数 | 描述 |
---|---|
stktrace() | 提供正在跟踪的 Java 应用程序 (正在运行的线程) 的堆栈跟踪。 |
copy_userdata() | 将数据从 java 应用程序复制到脚本变量。 |
get_probe() | 返回调查字符串。 |
get_stktrace | 返回运行时堆栈跟踪。 |
get_location_point() | 返回当前调查位置。 |
get_userstring() | 从 java 应用程序复制字符串数据。 |
exit() | 从 probevue 跟踪会话退出。 |
更改为 Probevue 命令:
命令 | 描述 |
---|---|
-X 选项 | 在当前版本中,用户必须手动传递额外的可选字符串 agentlib:probevuejava 以及运行 java 应用程序所需的所有其他选项。 |
例如:
probevue -X /usr/java5/bin/java -A -agentlib:probevuejava myjavaapp myscript.e
当运行 64 位 JVM 时,我们必须使用“agentlib:probevuejava64”,如下所示:
probevue -X /usr/java5_64/bin/java -A -agentlib:probevuejava64 myjavaapp myscript.e
where myjavaapp is the java class of myjavaapp.java application
示例 ExtendedClass.java 源:
class BaseClass
{
static int i=10;
public static void test(int x)
{
i += x;
}
}
public class ExtendedClass extends BaseClass
{
public static void test(int x, String msg)
{
i += x;
System.out.print("Java: " + msg + "\n\n");
BaseClass.test(x);
}
public static void main(String[] args)
{
BaseClass.test(5);
ExtendedClass.test(10, "hello");
}
}
针对以上 Java 应用程序的示例 test.e 脚本:
@@uftjava:$__CPID:*:"BaseClass.test":entry
{
printf("BaseClass.i: %d\n", BaseClass.i);
printf("BaseClass.test: %d\n", __arg1);
stktrace(0, -1);
printf("\n");
}
@@uftjava:$__CPID:*:"ExtendedClass.test":entry
{
printf("BaseClass.i: %d\n", BaseClass.i);
printf("ExtendedClass.test: %d, %s\n", __arg1, __arg2);
stktrace(0, -1);
printf("\n");
}
包含上述脚本的示例 ProbeVue 会话:
# probevue -X /usr/java5/jre/bin/java \
-A "-agentlib:probevuejava ExtendedClass" test.e
Java: hello
BaseClass.i: 10
BaseClass.test: 5
BaseClass.test()+0
ExtendedClass.main()+1
BaseClass.i: 15
ExtendedClass.test: 10, hello
ExtendedClass.test()+0
ExtendedClass.main()+8
BaseClass.i: 25
BaseClass.test: 10
BaseClass.test()+0
ExtendedClass.test()+39
ExtendedClass.main()+8