規則繫結
事件規範中包含一個繫結規範,用於在規則觸發時計算並引用變數的值。這些繫結值會在每次規則觸發時重新計算,並在測試規則條件之前使用。例如:
# 繫結示例
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 原創精華
【連載】從 Java 開始效能測試
- 混沌工程、故障測試、Web 前端
- 服務端功能測試
- 效能測試專題
- Java、Groovy、Go
- 白盒、工具、爬蟲、UI 自動化
- 理論、感悟、影片