隨著多核 CPU 的日益普及,越來越多的 Java 應用程式使用多線程並行計算來充分發揮整個系統的效能。多線程的使用也給應用程式開發人員帶來了巨大的挑戰,不正確地使用多線程可能造成線程死結或資源競爭,導致系統癱瘓。因此,需要一種運行時線程監控工具來協助開發人員診斷和跟蹤 Java 線程狀態的切換。JDK 1.5 及其後續版本提供了監控虛擬機器運行狀態的介面 JVMTI。
JVMTI 工具介面
隨著多核 CPU 技術的發展,多線程編程技術被廣泛地應用,從而充分發揮整個系統的效能。Java 語言對多線程編程提供了語言級的支援,可以方便地建立、運行、銷毀線程。然而,多線程的使用也給應用程式開發人員帶來了巨大的挑戰,不正確地使用多線程可能造成線程死結或資源競爭,導致系統癱瘓。
為了協助 Java 開發人員診斷和跟蹤 Java 線程狀態的切換,Sun 公司在 Java 開發套件(Java2 Software Development Kit, JDK)1.5.0 版本中引進了 JAVA 虛擬機器工具介面(Java Virtual Machine Toolkit Interface,JVMTI),用於替代在先前的 JDK 版本中作為實驗功能存在的 JAVA 虛擬機器剖析介面(Java Virtual Machine Profiling Interface,JVMPI)和 JAVA 虛擬機器調試介面(Java Virtual Machine Debugging Interface,JVMDI)。通過 JVMTI 介面可以建立代理程式(Agent)以監視和控制 Java 應用程式,包括剖析、調試、監控、分析線程等等,其架構模型如圖 1 所示。
圖 1. JVMTI 架構模型
Agent 可以向運行中的虛擬機器執行個體訂閱感興趣的事件,當這些事件發生的時候,會以事件回呼函數的方式啟用代理程式,同時 JVMTI 提供了眾多的功能函數,以查詢和控制 Java 應用程式的運行狀態。Agent 通過 JVMTI 所提供的介面與虛擬機器進行通訊,並同步監控虛擬機器的運行狀態,它與運行中的 Java 應用程式是相對獨立的,不會干擾程式的正常運行。Agent 可以用任何支援 C 語言標準的本地語言來編寫,並以動態連結程式庫的方式存在;Java 程式啟動的時候可以載入這個動態連結程式庫。
基於 JVMTI 介面構建的 Agent 可以方便地實現對 Java 線程狀態切換的跟蹤,從而使開發人員能夠在運行時清楚地瞭解多線程應用程式中線程的工作情況,方便進行調試和除錯。本文後續部分將介紹如何基於 JVMTI 介面構建 Java 線程切換監控代理。
Java 執行緒模式
要對 Java 線程的切換進行監控,必須先瞭解 JVM 中的 Java 執行緒模式。Java 執行緒模式可以用圖 2 所示的 Java 線程生命週期來描述。Java 線程的生命週期包括建立,就緒,運行,阻塞,死亡 5 個狀態。一個 Java 線程總是處於這 5 個生命週期狀態之一,並在一定條件下可以在不同狀態之間進行轉換 。
圖 2. Java 執行緒模式
建立狀態 (New Thread)
在 Java 語言中使用 new 操作符建立一個線程後,該線程僅僅是一個Null 物件,它具備了線程的一些特徵,但此時系統沒有為其分配資源,這時的線程處於建立狀態。
就緒狀態 (Runnable)
使用 start() 方法啟動一個線程後,系統為該線程分配了除 CPU 外的所需資源,使該線程處於就緒狀態。此外,如果某個線程執行了 yield() 方法,那麼該線程會被暫時剝奪 CPU 資源,重新進入就緒狀態。