规则绑定

事件规范中包含一个绑定规范,用于在规则触发时计算并引用变量的值。这些绑定值会在每次规则触发时重新计算,并在测试规则条件之前使用。例如:

# 绑定示例
RULE countdown at commit
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD commit
AT READ state
BIND engine:CoordinatorEngine = $0;
     recovered:boolean = engine.isRecovered();
     identifier:String = engine.getId()
. . .
ENDRULE

在此示例中,变量 engine 绑定到触发规则的 commit 方法调用的接收者,该接收者通过 $0 参数引用。如果 commit 是静态方法,则引用 $0 会导致类型检查异常。方法的参数可以通过 $1, $2 等索引访问。声明 engine 时可以指定类型为 CoordinatorEngine,但这不是必须的,因为类型可以从 $0 的类型推断。

类似地,变量 recoveredidentifier 通过右侧表达式计算值。类型说明符是可选的,未指定时系统会自动推断其类型。对于不需要绑定变量的规则,可以使用特殊语法 BIND NOTHING,或直接省略 BIND 子句。

向下转型的规则绑定

绑定初始化不仅用于为计算的值引入变量,还可以执行向下转型(downcast),将通用类型值分配给更具体的子类类型的规则变量。例如:

# 向下转型示例
RULE countdown at commit
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD commit
AT READ state
BIND engine:CoordinatorEngine = $0;
     endpoint:javax.xml.ws.EndpointReference = engine.participant;
     w3cEndpoint:javax.xml.ws.wsaddressing.W3CEndpointReference = endpoint
. . .
ENDRULE

在此规则中,engine.participant 的值被绑定到变量 endpoint,其类型为 EndpointReference。随后,变量 w3cEndpoint 使用 endpoint 的值,并通过向下转型声明为 W3CEndpointReference 类型。这在其他规则赋值中可能导致类型错误,但在绑定初始化中是允许的,前提是转换合法。

字节码检查器在初始化时会验证类型转换是否有效,并在失败时抛出异常。例如,假设 CoordinatorEngine 的字段 participant 被声明为 W3CEndpointReference 类型,则上述绑定永远不会失败。

向下转型在需要处理通用类型(如 List)时特别有用。由于泛型类型信息在编译时会被擦除,字节码检查器无法直接识别其具体类型。例如,通过列表检索的值总是被视为 Object 类型。如果已知列表存储的是特定类型的值,可以通过 BIND 子句将其向下转型为具体类型。

规则表达式

事件绑定中等号右侧的表达式可以是 Byteman 支持的任何 Java 表达式,包括:

表达式还可以由复杂组合构成,支持 Java 运算符,如 +, -, *, /, %, &&, ||, ==, !=, <, <= 等。三元运算符 ? : 也被支持。

特殊变量

规则条件

规则条件是布尔类型的表达式,用于决定规则是否触发。例如:

RULE countdown at commit
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD commit
AT READ state
BIND engine:CoordinatorEngine = $this;
     recovered:boolean = engine.isRecovered();
IF recovered
. . .
ENDRULE

上述条件测试绑定变量 recovered 的值是否为 true。以下示例使用方法调用直接作为条件:

IF engine.isRecovered()

如果相关字段直接存储布尔值,则条件可以简化为:

IF engine.recovered

对于始终触发的规则,可以使用布尔字面量 true 作为条件。

规则动作

规则动作可以是返回值、抛出异常、或分号分隔的表达式序列。支持的主要类型包括:

  1. 返回动作(return

    关键字 return 用于提前结束触发方法。如果方法非 void,需提供返回值。例如:

    DO return false
    
  2. 抛出动作(throw

    关键字 throw 可抛出运行时异常或触发方法声明的受检异常。例如:

    DO throw new RuntimeException("Error occurred")
    
  3. 空动作(NOTHING

    表示无具体动作。

内置调用

内置调用是由 Byteman 提供的工具方法,例如:

内置调用作为规则条件或动作的一部分执行,例如:

DO debug("killing JVM"), killJVM()

Byteman 允许通过扩展 Helper 类添加自定义内置调用,为规则提供更多功能。

FunTester 原创精华

【连载】从 Java 开始性能测试


↙↙↙阅读原文可查看相关链接,并与作者交流