规则绑定
事件规范中包含一个绑定规范,用于在规则触发时计算并引用变量的值。这些绑定值会在每次规则触发时重新计算,并在测试规则条件之前使用。例如:
# 绑定示例
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
的类型推断。
类似地,变量 recovered
和 identifier
通过右侧表达式计算值。类型说明符是可选的,未指定时系统会自动推断其类型。对于不需要绑定变量的规则,可以使用特殊语法 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 表达式,包括:
- 绑定变量的引用。
- 触发方法的接收者或参数的引用。
- 触发点范围内局部变量的引用。
- 特殊变量
$!
、$^
、$#
、$*
、$@
、$CLASS
和$METHOD
的引用。 - 静态字段或实例字段的引用。
- 原始字面量或数组字面量。
- 方法调用(静态或实例)。
- 内置操作调用。
表达式还可以由复杂组合构成,支持 Java 运算符,如 +
, -
, *
, /
, %
, &&
, ||
, ==
, !=
, <
, <=
等。三元运算符 ? :
也被支持。
特殊变量
-
$!
:绑定触发点处的返回值,在AT EXIT
和AFTER INVOKE
规则中有效。 -
$^
:绑定触发点处抛出的异常,在AT THROW
和AT EXCEPTION EXIT
规则中有效。 -
$#
:绑定为触发方法的参数数量。 -
$*
:绑定为包含触发方法接收者和参数的Object[]
数组。 -
$@
:在AT INVOKE
规则中有效,绑定为目标方法的接收者及调用参数数组。 -
$CLASS
:绑定为触发规则的类的完全限定名。 -
$METHOD
:绑定为触发规则的方法的完整签名。 -
$NEWCLASS
:在AT NEW
和AFTER NEW
规则中有效,绑定为新操作创建的类名。
规则条件
规则条件是布尔类型的表达式,用于决定规则是否触发。例如:
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
作为条件。
规则动作
规则动作可以是返回值、抛出异常、或分号分隔的表达式序列。支持的主要类型包括:
-
返回动作(
return
)
关键字return
用于提前结束触发方法。如果方法非void
,需提供返回值。例如:DO return false
-
抛出动作(
throw
)
关键字throw
可抛出运行时异常或触发方法声明的受检异常。例如:DO throw new RuntimeException("Error occurred")
空动作(
NOTHING
)
表示无具体动作。
内置调用
内置调用是由 Byteman 提供的工具方法,例如:
-
debug(String)
:打印调试信息。 -
killJVM()
:立即终止 JVM,模拟崩溃。
内置调用作为规则条件或动作的一部分执行,例如:
DO debug("killing JVM"), killJVM()
Byteman 允许通过扩展 Helper
类添加自定义内置调用,为规则提供更多功能。
FunTester 原创精华