簡介
本文的目的是提供關於 DB2 for Linux, UNIX, and Windows 跟蹤功能的背景知識,以及如何在強大的 Eclipse Modeling Framework (EMF) 中使用它檢測應用程序資源洩漏。本文將介紹如何在 DB2 中啟用跟蹤 Java® 應用程序對數據庫資源的訪問的機制,以及如何開發一個自定義 Eclipse 插件來分析生成的跟蹤文件。通過分析跟蹤文件,您可以檢測異常的應用程序行為,比如數據庫資源漏洩。本文還將討論如何開發 Eclipse 插件,並將詳細討論如何開發 EMF 插件。
本文並不打算采用 “DB2 應用程序開發:使用 DB2 Universal JDBC Driver 執行跟蹤” 這篇文章的套路,或者借鑒關於 DB2 跟蹤機制的任何其他文章 — 而僅僅是介紹一個輕松高效地分析 DB2 跟蹤文件的示例用例。
領域特定語言 (DSL) 用於描述單一域中的元素(可能范圍很小)。舉例來說,這個域可以是家庭樹或 .ini 配置文件元素。在本文中,您可以認為用於生成 DB2 跟蹤文件的語言是領域特定語言。
如今,DSL 並沒有得到非常廣泛的應用,因為 Extensible Markup Language(XML)以其優勢已經占據了穩固的地位。但在某些領域,XML 有點太過於 “冗長” 和笨拙。這些領域就成了 DSL 展示自己的舞台 — DSL 通常包含描述功能域所需的一切,並且不包含任何不需要功能,或者添加不必要的語言開銷。
DSL 的使用可能會對讀取使用 DSL 編寫的內容的工具造成明顯的影響 — 在這種場景中,通常都需要編寫一個自定義解析器。您經常會發現組織有序的應用程序可以幫助您完成這類活動 — 比如基於 ANTLR 的工具和插件。
要應用這篇文章,您需要了解 IBM DB2 產品、Java 編程語言、JDBC 技術、Eclipse 平台和 EMF 的基礎知識。
DB2 跟蹤機制詳細信息
DB2 Information Center提供了關於適用於 Java Database Connectivity (JDBC) 連接的內置 DB2 跟蹤的全面信息。本節將重點介紹一些基本特性。
借助 DB2 JDBC 跟蹤機制,您可以收集關於應用程序向數據庫服務器發起的數據庫查詢的詳細信息。它將還為您提供關於查詢結果以及其他重要元數據的信息。DB2 跟蹤文件包含大多數 DB2 服務器信息、所有 JDBC 連接細節和所有 SQL 查詢等。嘗試檢測資源洩漏時,JDBC 提供的一些最相關的數據會告訴您 SQL 連接、SQL 語句和 SQL 結果集是否已被連接的應用程序正確關閉。
當應用程序分配了資源,但此後未聲明不再使用資源時(比如通過發起 close() 操作)便會出現數據庫資源洩漏。DB2 跟蹤文件包含 DB2 連接、語句、已打開但從未關閉的結果集的列表。這些資源要麼是持續使用中,要行是已經發生了洩漏。資源洩漏會造成 DB2 服務器負載過大,應用程序出現異常行為,或者甚至造成 DB2 服務器崩潰。
在使用 JDBC 技術連接 DB2 服務器的 Java 應用程序中,可以輕松地啟動 DB2 跟蹤。將需將以下參數附加到應用程序所使用的 JDBC URL 字符串中:
traceDirectory — 希望存放這些文件的目錄。
traceFile — 希望為各跟蹤文件名使用的前綴。
traceLevel — 希望使用的跟蹤級別。您可以選擇跟蹤所有可能的調用,並接收所有跟蹤數據,或者也可以使用過濾器僅跟蹤最相關的信息。有關不同跟蹤級別的詳細信息,請訪問 DB2 Information Center。
啟用應用程序並通過 DBC URL 傳遞正確的跟蹤參數之後,應該開始創建跟蹤文件了。需要為每個打開的 SQL 連接都創建一個單獨的文件。
清單 1 顯示了 DB2 跟蹤文件的一個示例。注意,為了在本文中正確顯示它,我們將較長的代碼行分開了。
清單 1. 示例 DB2 跟蹤文件
[ibm][db2][jcc] BEGIN TRACE_DRIVER_CONFIGURATION
[ibm][db2][jcc] Driver: IBM DB2 JDBC Universal Driver Architecture 2.3.63
[ibm][db2][jcc] Compatible JRE versions: { 1.3, 1.4 }
…
[ibm][db2][jcc][Time:1250166693938][Thread:main][Connection@67df5ee8]
getAutoCommit () returned true
[ibm][db2][jcc][Time:1250166693938][Thread:main][Connection@67df5ee8]
clearWarnings () called
[ibm][db2][jcc][Time:1250166693938][Thread:main][Connection@67df5ee8]
getMetaData () returned DatabaseMetaData@721cdee9
[ibm][db2][jcc][Time:1250166693938][Thread:main][Connection@67df5ee8]
setTransactionIsolation (2) called
[ibm][db2][jcc][Time:1250166698906][Thread:main][Connection@67df5ee8]
getAutoCommit () returned true
[ibm][db2][jcc][Time:1250166698906][Thread:main][Connection@67df5ee8]
clearWarnings () called
[ibm][db2][jcc][Time:1250166698906][Thread:main][Connection@67df5ee8]
getMetaData () returned DatabaseMetaData@721cdee9
[ibm][db2][jcc][Time:1250166698906][Thread:main][Connection@67df5ee8]
setTransactionIsolation (2) called
[ibm][db2][jcc][Time:1250166698906][Thread:main][Connection@67df5ee8]
prepareStatement (select OBJ_ID from SCHEMA_NAME.OBJECT_CLASS
where CLASSNAME=?) called
[ibm][db2][jcc][Time:1250166698906][Thread:main][Connection@67df5ee8]
prepareStatement () returned PreparedStatement@6d0f1ee0
[ibm][db2][jcc][Time:1250166698906][Thread:main][PreparedStatement@6d0f1ee0]
setObject (1, Java.lang.String) called
Eclipse Modeling Framework 基礎
如 EMF 項目網站所述,EMF 是一個構建框架和代碼生成工具,用於根據結構化的數據模型構建工具和其他應用程序。除了用於管理模型的一系列實用工具之外,EMF 還提供了一組相當復雜的高級的功能,可用於創建能提供用戶友好圖形界面的 Eclipse 插件,用於查看和操作域模型的內容。
EMF 可以使用模型生成以下 Eclipse 插件:
模型插件 — 包含模型定義
模型編輯插件 — 允許操作模型實例
模型查看器插件 — 提供的視圖可以幫助您輕松地導航和查看關於模型實例內容的詳細信息
所生成的 EMF 插件的完整集合允許您打開、查看、甚至修改模型數據文件。以下小節將討論如何為 DB2 跟蹤文件創建模型,基於該模型生成一組 EMF 插件,並使用這些插件幫助檢測資源洩漏。
針對 DB2 跟蹤文件的 EMF 模型
在創建讀取和呈現 DB2 跟蹤文件內容的 EMF 插件之前,您首先需要創建相應的 EMF 模型。該模型將定義域的各元素之間的關系(此場景中的域為 DB2 跟蹤文件元素)以及元素本身。您可以通過 UML 模型生成 EMF 模型,或者重新開始創建它。由於此場景中的模型並不復雜,並且未涉及冗長的建模方法,因此本文僅討論如何從重新開始創建模型。
在創建 EMF 模型之前,您至少需要一個 DB2 跟蹤文件。您需要跟蹤文件的原因是可以查看它的內容,並確定它所包含的元素。在發現應用程序中的資源洩漏方面,以下元素是最相關的(連接、語句或結果集):
DB2 Server 元數據— 包含 DB2 Server 產品名稱和版本,以及 JDBC 驅動程序名稱和版本
DB2 連接詳細信息 — 包含連接和用戶名所使用的 JDBC URL
操作系統詳細信息 — 關於操作系統的詳細信息
JVM 詳細信息 — 關於跟蹤應用程序所使用的 JVM 的詳細信息
跟蹤應用程序所使用的語句列表和結果集
除了上面列出的項目之外,DB2 跟蹤文件還包含其他一些元素。它們對於全面理解跟蹤應用程序如何使用數據庫服務器非常重要。
本文的作用域並不包括創建 EMF 模型的詳細信息。有關詳細信息,請訪問 Eclipse Modeling Framework 項目網站。
圖 1 顯示了為 DB2 跟蹤文件元素創建的 EMF 模型的一個示例,它可以幫助發現資源洩漏。它們與以上列表中描述的跟蹤文件元素相同。
圖 1. DB2 跟蹤文件內容的基本 EMF 模型
基於 EMF 模型生成 EMF 插件
創建 EMF 模型之後,您可以使用 EMF 自動生成一組 EMF 插件。這些插件包含用於讀取、操作和保存模型跟蹤文件的內容的代碼。其中一些插件是用於呈現模型 DB2 跟蹤文件的內容的 Eclipse 視圖。您可以使用這個插件來查看 DB2 跟蹤文件並檢測資源漏洩。
要從模型文件生成 EMF 插件,請執行以下操作:
在 Eclipse 環境中打開 EMF 模型文件。
右鍵單擊該模型。
從上下文菜單中,選擇 Generate All。
這將創建以下插件:
edit
editor
tests
定制 EMF 編輯器插件使用資源工廠
默認情況下,EMF 模型的實例將被序列化為使用 XML Metadata Interchange (XMI) 格式的文件。這意味著模型文件將被解釋為 XML 文件。EMF 提供了一個特性來支持這種格式的文件。
您還可以提供自己的 Java 類來讀取和保存自定義格式的文件。這些類表示 EMF 資源工廠。
資源工廠的基本 EMF 框架類是 org.eclipse.emf.ecore.resource.Resource.Factory 接口,其基本實現是 org.eclipse.emf.ecore.resource.impl.ResourceFactoryImpl。該工廠負責提供一個 org.eclipse.emf.ecore.resource.Resource 實例。Resource 類是一個基類,它包含用於操作 EMF 資源的方法,包括讀取和保存內容的方法。要讀取 DB2 跟蹤文件,您只需要提供用於讀取跟蹤文件格式(而不是 XML 格式)的自定義實現。
要讀取 DB2 跟蹤格式,您需要為 DB2 跟蹤文件格式提供解析器(領域特定語言)。可行的兩種方案如下:
重新編寫一個解析器。
使用解析器生成器框架(比如 ANTLR)。
無論決定如何創建解析器,您都需要理解 DB2 跟蹤文件的語法,並為此語法設計文法。
DB2 跟蹤文件基本語法
在此場景中,您最關心的是 EMF 模型中用於檢測數據庫資源洩漏的跟蹤文件元素。
以下 EMF 元素是通過相應的 DB2 跟蹤文件行構建的:
DB2 服務器元數據將由以下部分表示:
Database product version
Driver name
Driver version
DB2 連接詳細信息包括:
Successfully connected to server
User:
操作系統詳細信息包含在使用以下內容開頭的行中:
Operating system
JVM 詳細信息包含在使用以下內容開頭的行中:
Java
JDBC 語句列出在包含以下內容的行中:
[Connection@<Connection ID>] createStatement
PreparedStatements 列出在包含以下內容的行中:
[Connection@<Connection ID>] prepareStatement
結果集詳細信息列出在包含以下內容的行中:
[ResultSet@<ResultSet ID>]
為了檢測哪些資源已被關閉,解析器應該在 DB2 跟蹤文件中查找包含以下內容的行:
[<Resource ID>] close () called
其中,<Resource ID> 表示以下項目之一:
Statement
PreparedStatement
ResultSet
創建自定義 EMF 資源工廠
使用之前介紹的 DB2 跟蹤文件元素來設計在 ANTLR 中使用的語法,或者編寫自定義解析器(用於讀取 DB2 跟蹤文件的內容以及創建 EMF 建模類的實例)。這些類是由 EMF 框架生成的。它們所在的 EMF 插件包含 EMF 模型,並且擴展了 org.eclipse.emf.ecore.EObject 基類。以下行將創建一個 PreparedStatement 建模類實例,並修改其屬性:
PreparedStatement pStmt = traceFactory.createPreparedStatement();
pStmt.setID(statementID);
pStmt.setQuery(queryString);
實現解析器並創建有效的 EMF 模型實例之後,必須將它綁定到 EMF 資源工廠中。
使用 org.eclipse.emf.ecore.resource.Resource.Factory.Registry 類的默認實例注冊自定義 EMF 資源工廠實現,如下所示:
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap()
.put(resourceURI.fileExtension(), new MyCustomDB2TraceResourceFactoryImpl());
注意,上面顯示的代碼實際上只有一行。為正常顯示,本文將它分開了。
實現以上行之後,所有的資源將被自定義資源類處理。這意味著您可以使用自己的 EMF 插件集來打開和分析任何 DB2 跟蹤文件。
使用 EMF 插件檢測資源漏洩
在啟用 DB2 JDBC 選項的情況下執行 Java 應用程序之後,您可以使用新的 EMF 插件來分析跟蹤文件。為此,只需要啟動安裝了 EMF 插件的 Eclipse 環境,然後打開一個或多個 DB2 跟蹤文件。
打開 DB2 跟蹤文件之後,EMF 插件會將一個樹形結構中顯示其內容。當您選擇樹形結構中的某個元素時,它會激活屬性視圖並顯示所選項目的詳細信息。
圖 2 顯示了 EMF 樹形視圖的一個示例,其下文是一個 EMF 元素屬性視圖。
圖 2. 使用 EMF 插件的 DB2 跟蹤文件的樹形和屬性視圖
您可以使用樹形視圖導航 DB2 跟蹤文件。您可以查看創建了哪些相關元素,比如 JDBC 連接、語句、已備語句和結果集,以及發起了哪些查詢。
在查找資源洩漏時,需要重點注意的一個地方是與 JDBC 對象 Statement/PreparedStatement 相關的 SQL 查詢,以及是否調用了 close() 方法。close() 方法負責釋放與調用方法所針對的 JDBC 元素相關的所有數據庫資源。經過精心設計、使用 JDBC 框架的 Java 應用程序應該會在數據庫資源不需要時立即釋放它們。
如果應用程序未關閉 JDBC 連接,那麼您通常需要深入分析原因。有時,在應用程序終止之前不能關閉 JDBC 連接(比如,需要提供 JDBC 連接池)。因此,您需要逐一分析每種特殊情況。
DB2 跟蹤機制簡化了分析任務,但跟蹤文件更加復雜並且很難手動進行分析。使用 EMF 插件讀取 DB2 跟蹤文件並可視呈現內容,可以更加輕松地分離和識別未正常處理的資源。
在圖 3 所示的示例中,我們使用 EMF 插件查看 ID 為 174 的 JDBC 連接的詳細信息。詳細屬性視圖顯示連接的 Close Called 屬性為 false。這表示應用程序並未關閉連接。因此,在本例中,您需要深入分析出現這種情況的原因。如果確定 JDBC 連接未處理處理,並且所屬應用程序 “忘記” 關閉它,則表示您發現了一處需要修復的資源洩漏。
圖 3. 未關閉 JDBC 連接,這表示應用程序存在問題
結束語
本文展示了如何將 IBM DB2 跟蹤機制與 Eclipse Modeling Framework 結合使用。它闡述了如何生成強大的 EMF 插件,用於分析 DB2 跟蹤文件並迅速檢測支持 Java 數據庫的應用程序中的異常行為。這將為您節省寶貴的時間,否則您將需要手動分析 DB2 跟蹤文件。