多核時代,Java 併發程式效能調優的關鍵在於鎖爭用與可擴展性分析。傳統工具(JLM 等)僅支援傳統 `synchronized` 鎖,對 `java.util.concurrent.locks` (JUC) 鎖無能為力。IBM Multicore SDK 隨附的 jucprofiler 填補此空白,提供 JUC 鎖爭用時間、等待時間、調用堆疊的完整可視化分析。
啟動前需執行命令生成 PreInstrument.jar(替換 JRE 中相關類),僅需執行一次(除非 JRE 更新)。儀器化目標類與方法:
| 類型 | 類 | 方法 | 調用位置 |
|---|---|---|---|
| 爭用 | AbstractQueuedSynchronizer | parkAndCheckInterrupt() | LockSupport.park(Object) |
| 爭用 | AbstractQueuedSynchronizer | doAcquireNanos / doAcquireSharedNanos | LockSupport.parkNanos(Object, long) |
| 等待 | AbstractQueuedSynchronizer$ConditionObject | await / awaitNanos 等 | LockSupport.park / parkNanos (非上述爭用位置) |
java -Xbootclasspath/p:$JUCP/BCIRuntime.jar:$JUCP/PreInstrument.jar \
-javaagent:$JUCP/BCIAgent.jar=callStackDepth=10:allocationStackDepth=0 \
:msdk.idp=com.ibm.msdk.bciagent.JUCInstrumentDecisionProvider \
:libPath=$JUCP:traceJUC=on \
-cp .:derby.jar JavaDBDemo
生成追蹤檔 BCIAgent.***.bci.trace。
java -Xmx1000m -jar $JUCP/BCITraceReader.jar {tracefile} {resultOutputFile}
建議配置大堆(如 160MB 追蹤檔需 800MB 堆)。
摘要區:按爭用次數/時間降序列出所有 JUC 鎖(AQS@id)與 `ConcurrentHashMap` 片段群組(CHM@id)。
NAME CONTD-COUNT CONTD-TIME(ns) HOLD-COUNT HOLD-TIME
CHM@8 276 39,457,000 0 0
AQS@1790 36 4,029,000 0 0
AQS@131 17 630,000 0 0
詳情區:每個鎖的逐次爭用記錄,含調用堆疊。範例顯示 `CHM@8` 內兩個片段鎖 `AQS@135`、`AQS@146` 的爭用堆疊,直指 `ConcurrentHashMap$Segment.remove` → `ConcurrentLockSet.unlock`,精準定位熱點。
Eclipse 外掛提供兩視圖:


執行期間監聽 2009 連接埠,支援動態開關追蹤:
jucprofiler 以極低侵入性(Byte Code Instrumentation)精準捕獲 JUC 鎖爭用與等待行為,配合可視化工具與線上控制,成為多核 Java 併發效能調優的利器。隨著並行程式普及,此類專用分析工具將愈發關鍵。