JavaTM Platform
Standard Ed. 6

软件包 java.lang.instrument

提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。

请参见:
          描述

接口摘要
ClassFileTransformer 一个提供此接口的实现以转换类文件的代理。
Instrumentation 此类提供检测 Java 编程语言代码所需的服务。
 

类摘要
ClassDefinition 此类用作 Instrumentation.redefineClasses 方法的参数锁定。
 

异常摘要
IllegalClassFormatException 当其输入参数无效时,由 ClassFileTransformer.transform 的实现抛出该异常。
UnmodifiableClassException 在无法修改指定类之一时,由 Instrumentation.redefineClasses 的实现抛出此异常。
 

软件包 java.lang.instrument 的描述

提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。检测机制是对方法的字节码进行修改。

包规范

代理被部署为 JAR 文件。JAR 文件清单中的属性指定将被加载以启动代理的代理类。对于支持命令行接口的实现,可以在命令行指定一个选项来启动代理。实现也支持在 VM 启动后某一时刻启动代理的机制。例如,实现可以提供一种机制,允许某种工具连接 到运行的应用程序,并将该工具代理的加载初启到该应用程序中。如何初启加载的细节与实现有关。

命令行接口

对于使用命令行接口的实现,可以将以下选项添加到命令行来启动代理:

-javaagent: jarpath[ = options]
jarpath 是代理 JAR 文件的路径。 options 是代理选项。 此开关可以在同一代码行使用多次,从而创建多个代理。 多个代理可以使用相同的 jarpath。 代理 JAR 文件必须遵守 JAR 文件规范。

代理 JAR 文件的清单必须包含 Premain-Class 属性。此属性的值是代理类 的名称。代理类必须实现公共静态 premain 方法,该方法的原理与 main 应用程序入口点类似。在 Java 虚拟机 (JVM) 初始化后,每个 premain 方法将按照指定代理的顺序调用,然后将调用实际的应用程序 main 方法。每个 premain 方法必须按照依次进行的启动顺序返回。

premain 方法有两种可能的签名。JVM 首先尝试在代理类上调用以下方法:

public static void premain(String agentArgs, Instrumentation inst);

如果代理类没有实现此方法,那么 JVM 将尝试调用:

public static void premain(String agentArgs);

如果代理在 VM 启动之后启动,那么代理类还有一个要使用的 agentmain 方法。如果是使用命令行选项启动代理,那么 agentmain 方法将不会被调用。

代理类将被系统类加载器加载(参见 ClassLoader.getSystemClassLoader)。系统类加载器是通常加载包含应用程序 main 方法的类的类加载器。 premain 方法将在与应用程序 main 方法相同的安全性和类加载器规则下运行。不存在代理 premain 方法可以执行的建模限制。任何应用程序 main 可以执行的事情(包括创建线程)对于 premain 都是合法的。

每个代理通过 agentArgs 参数传递其代理选项。代理选项作为单个字符串传递,任何其他解析应由代理本身执行。

如果该代理不能被解析(例如,由于无法加载代理类,或者代理类没有恰当的 premain 方法),那么 JVM 将中止。如果 premain 方法抛出未捕获的异常,那么 JVM 将中止。

VM 启动后启动代理

实现可以提供一种机制在 VM 启动之后某一时刻启动代理。如何初启的细节是特定于实现的,但通常应用程序已经启动并且其 main 方法已经调用。如果实现支持在 VM 启动之后启动代理,则以下内容适用:

  1. 代理 JAR 的清单必须包含属性 Agent-Class。此属性的值是代理类 的名称。

  2. 代理类必须实现公共静态 agentmain 方法。

  3. 系统类加载器(ClassLoader.getSystemClassLoader)必须支持将代理 JAR 文件添加到系统类路径的机制。

代理 JAR 将被添加到系统类路径。系统类路径是通常加载包含应用程序 main 方法的类的类路径。代理类将被加载,JVM 尝试调用 agentmain 方法。JVM 首先尝试对代理类调用以下方法:

public static void agentmain(String agentArgs, Instrumentation inst);

如果代理类没有实现此方法,那么 JVM 将尝试调用:

public static void agentmain(String agentArgs);

如果代理是使用命令行选项启动的,那么代理类还有一个要使用的 agentmain 方法。如果是在 VM 启动之后启动代理,那么 agentmain 方法将不会被调用。

代理通过 agentArgs 参数传递其代理选项。代理选项作为单个字符串传递,任何其它解析应该由代理本身执行。

agentmain 方法应该执行任何启动代理所需的初始化。启动完成时该方法应返回。如果代理无法启动(例如,由于无法加载代理类,或者代理类没有构造 agentmain 方法),那么 JVM 将中止。如果 agentmain 方法抛出未捕获的异常,那么它将被忽略。

清单属性

以下清单属性是针对代理 JAR 文件定义的:
Premain-Class
如果 JVM 启动时指定了代理,那么此属性指定代理类,即包含 premain 方法的类。如果 JVM 启动时指定了代理,那么此属性是必需的。如果该属性不存在,那么 JVM 将中止。注:此属性是类名,不是文件名或路径。
Agent-Class
如果实现支持 VM 启动之后某一时刻启动代理的机制,那么此属性指定代理类。 即包含 agentmain 方法的类。 此属性是必需的,如果不存在,代理将无法启动。 注:这是类名,而不是文件名或路径。
Boot-Class-Path
由引导类加载器搜索的路径列表。路径表示目录或库(在许多平台上通常作为 JAR 或 zip 库被引用)。查找类的特定于平台的机制失败后,引导类加载器会搜索这些路径。按列出的顺序搜索路径。列表中的路径由一个或多个空格分开。路径使用分层 URI 的路径组件语法。如果该路径以斜杠字符(“/”)开头,则为绝对路径,否则为相对路径。相对路径根据代理 JAR 文件的绝对路径解析。忽略格式不正确的路径和不存在的路径。如果代理是在 VM 启动之后某一时刻启动的,则忽略不表示 JAR 文件的路径。此属性是可选的。
Can-Redefine-Classes
布尔值( truefalse,与大小写无关)。是否能重定义此代理所需的类。 true 以外的值均被视为 false。此属性是可选的,默认值为 false
Can-Retransform-Classes
布尔值( truefalse,与大小写无关)。是否能重转换此代理所需的类。 true 以外的值均被视为 false。此属性是可选的,默认值为 false
Can-Set-Native-Method-Prefix
布尔值( truefalse,与大小写无关)。是否能设置此代理所需的本机方法前缀。 true 以外的值均被视为 false。此属性是可选的,默认值为 false

代理 JAR 文件在清单中可以同时出现 Premain-ClassAgent-Class 属性。如果代理是使用 -javaagent 选项在命令行上启动的,那么 Premain-Class 属性指定代理类的名称,Agent-Class 属性将被忽略。类似地,如果代理是在 VM 启动后某一时刻启动的,那么 Agent-Class 属性指定代理类的名称(Premain-Class 属性的值将被忽略)。

相关文档

有关工具文档的信息,请参阅:

从以下版本开始:
JDK1.5

JavaTM Platform
Standard Ed. 6

提交错误或意见
有关更多的 API 参考资料和开发人员文档,请参阅 Java SE 开发人员文档。该文档包含更详细的、面向开发人员的描述,以及总体概述、术语定义、使用技巧和工作代码示例。

版权所有 2007 Sun Microsystems, Inc. 保留所有权利。 请遵守许可证条款。另请参阅文档重新分发政策