Atitit.獲取swing?ui?按鈕控件的id?與名字?與JPDA?調(diào)試體系
?
1.?Swing?Inspector是一個Java?Swing/AWT用戶界面分析和調(diào)試工具,功能與firebug類似,2
6.?JPDA(Java?Platform?Debugger?Architecture)是?Java?平臺調(diào)試體系結(jié)構(gòu)的縮寫。4
6.6.2.?Java?調(diào)試線協(xié)議(JDWP)9
?
1.?Swing?Inspector是一個Java?Swing/AWT用戶界面分析和調(diào)試工具,功能與firebug類似,具有強大的Swing/AWT用戶界面分析和調(diào)試相關(guān)功能。?適用于從java?swing初級到高級的所有開發(fā)人員,能夠快速定位問題,UI快速調(diào)試,分析其他軟件界面的實現(xiàn)原理,能夠給開發(fā)工作效率帶來大幅提升。
特點:
1.?具備UI組件聯(lián)動功能,在用戶界面中Ctrl+移動鼠標(Mac?OSX??+F12),可以在Swing?Inspector主界面中顯示對應(yīng)組件信息,并高亮當前Component。
2.?可以在Swing?Inspector組件樹中聯(lián)動到用戶界面,即雙向聯(lián)動,且不需要提供界面的源代碼。
3.?Applet支持,可以定位嵌入到任何網(wǎng)頁中的applet界面。
4.?強大的window捕獲功能,可以捕獲加載agent的jvm創(chuàng)建的所有Swing/AWT窗口(網(wǎng)頁中的applet,瀏覽器加載appet/webstart后啟動的console窗口),模式對話框等。
5.?綠色,無需安裝,只需給java命令添加一行參數(shù),即可啟動Swing?Inspector。
6.?支持所有的AWT/Swing程序,netbeans、visualvm等。
7.?強大的表達式支持,允許對選定組進執(zhí)行表達式運算,實時顯示計算結(jié)果,運算結(jié)果支持屬性瀏覽和編輯。
8.?強大的Javascript支持功能,支持用javascript實時修改用戶界面中的組件,執(zhí)行腳本后立即生效。
9.?高性能,核心功能采用c/c++實現(xiàn),直接操縱jvm,對性能影響很小,主界面采用lazy機制,刷新組件時只更新可見viewer。屬性編輯器可直接修改選定的組件屬性,且直接生效。
10.?可以記錄組件添加到parent時的stacktrace,可以快速定位到相應(yīng)的代碼行。
11.?簡單易用,快捷鍵與常用軟件一致(F5刷新、Alt+Left后退,Alt+Right前進等),界面非常簡潔、直觀,沒有學(xué)習(xí)成本。
12.?免費,為軟件行業(yè)發(fā)展盡一份力量是我們的宗旨
?
?
作者:: 老哇的爪子 Attilax 艾龍
轉(zhuǎn)載請注明來源:?
?
2.?類似spylite?,firebug 3.?Eclipse??vm?param?
-agentpath:E:swing-inspector-windows-1.2.2_beta7Win32swing-inspector-agent.dll
4.?Cltr+f12顯示主界面?
5.?Ctrl+鼠標找到控件?
?
?
Create?StackTrace?-?javax.swing.JLabel@7293796
????com.openbravo.pos.sales.JPanelTicket.initComponents(JPanelTicket.java:1226)
????com.openbravo.pos.sales.JPanelTicket.(JPanelTicket.java:187)
????com.openbravo.pos.sales.JPanelTicketSales.(JPanelTicketSales.java:18)
????aaaAtiDslParser.aaa33.main(aaa33.java:29)?
?
?
6.?javaagent的主要功能如下:·?可以在加載class文件之前做攔截,對字節(jié)碼做修改?
·?可以在運行期對已加載類的字節(jié)碼做變更,但是這種情況下會有很多的限制,后面會詳細說?
·?還有其他一些小眾的功能?
o?獲取所有已經(jīng)加載過的類?
o?獲取所有已經(jīng)初始化過的類(執(zhí)行過clinit方法,是上面的一個子集)?
o?獲取某個對象的大小?
o?將某個jar加入到bootstrap?classpath里作為高優(yōu)先級被bootstrapClassloader加載?
o?將某個jar加入到classpath里供AppClassloard去加載?
o?設(shè)置某些native方法的前綴,主要在查找native方法的時候做規(guī)則匹配?
?
?
7.?JPDA(Java?Platform?Debugger?Architecture)是?Java?平臺調(diào)試體系結(jié)構(gòu)的縮寫。通過?JPDA?提供的?API,開發(fā)人員可以方便靈活的搭建?Java?調(diào)試應(yīng)用程序。?JPDA?主要由三個部分組成:Java?虛擬機工具接口(JVMTI)、Java?調(diào)試線協(xié)議(JDWP),以及?Java?調(diào)試接口(JDI)。
?
?
7.1.?Java?調(diào)試接口的特點
Java?語言是第一個使用虛擬機概念的流行的編程語言,正是因為虛擬機的存在,使很多事情變得簡單而輕松,掌握了虛擬機,就掌握了內(nèi)存分配、線程管理、即時優(yōu)化等等運行態(tài)。同樣的,Java?調(diào)試的本質(zhì),就是和虛擬機打交道,通過操作虛擬機來達到觀察調(diào)試我們自己代碼的目的。這個特點決定了?Java?調(diào)試接口和以前其他編程語言的巨大區(qū)別。
以?C/C++?的調(diào)試為例,目前比較流行的調(diào)試工具是?GDB?和微軟的?Visual?Studio?自帶的?debugger,在這種?debugger?中,首先,我們必須編譯一個“?debug?”模式的程序,這個會比實際的?release?模式程序大很多。其次,在調(diào)試過程中,debugger?將會深層接入程序的運行,掌握和控制運行態(tài)的一些信息,并將這些信息及時返回。這種介入對運行的效率和內(nèi)存占用都有一定的需求?;谶@些需求,這些?Debugger?本身事實上是提供了,或者說,創(chuàng)建和管理了一個運行態(tài),因此他們的程序算法比較復(fù)雜,個頭都比較大。對于遠端的調(diào)試,GDB?也沒有很好的默認實現(xiàn),當然,C/C++?在這方面也沒有特別大的需求。
?
?
而?Java?則不同,由于?Java?的運行態(tài)已經(jīng)被虛擬機所很好地管理,因此作為?Java?的?Debugger?無需再自己創(chuàng)造一個可控的運行態(tài),而僅僅需要去操作虛擬機就可以了。?Java?的?JPDA?就是一套為調(diào)試和優(yōu)化服務(wù)的虛擬機的操作工具,其中,JVMTI?是整合在虛擬機中的接口,JDWP?是一個通訊層,而?JDI?是前端為開發(fā)人員準備好的工具和運行庫。
從構(gòu)架上說,我們可以把?JPDA?看作成是一個?C/S?體系結(jié)構(gòu)的應(yīng)用,在這個構(gòu)架下,我們可以方便地通過網(wǎng)絡(luò),在任意的地點調(diào)試另外一個虛擬機上的程序,這個就很好地解決了部署和測試的問題,尤其滿足解決了很多網(wǎng)絡(luò)時代中的開發(fā)應(yīng)用的需求。前端和后端的分離,也方便用戶開發(fā)適合于自己的調(diào)試工具。
從效率上看,由于?Java?程序本身就是編譯成字節(jié)碼,運行在虛擬機上的,因此調(diào)試前后的程序、內(nèi)存占用都不會有大變化(僅僅是啟動一個?JDWP?所需要的內(nèi)存),任意程度都可以很好地調(diào)試,非常方便。而?JPDA?構(gòu)架下的幾個組成部分,JDWP?和?JDI?都比較小,主要的工作可以讓虛擬機自己完成。
從靈活性上,Java?調(diào)試工具是建立在強大的虛擬機上的,因此,很多前沿的應(yīng)用,比如動態(tài)編譯運行,字節(jié)碼的實時替換等等,都可以通過對虛擬機的改進而得到實現(xiàn)。隨著虛擬機技術(shù)的逐步發(fā)展和深入,各種不同種類,不同應(yīng)用領(lǐng)域中虛擬機的出現(xiàn),各種強大的功能的加入,給我們的調(diào)試工具也帶來很多新的應(yīng)用。
總而言之,一個先天的,可控的運行態(tài)給?Java?的調(diào)試工作,給?Java?調(diào)試接口帶來了極大的優(yōu)勢和便利。通過?JPDA?這個標準,我們可以從虛擬機中得到我們所需要的信息,完成我們所希望的操作,更好地開發(fā)我們的程序。
?
7.2.?JPDA?組成模塊
JPDA?定義了一個完整獨立的體系,它由三個相對獨立的層次共同組成,而且規(guī)定了它們?nèi)咧g的交互方式,或者說定義了它們通信的接口。這三個層次由低到高分別是?Java?虛擬機工具接口(JVMTI),Java?調(diào)試線協(xié)議(JDWP)以及?Java?調(diào)試接口(JDI)。這三個模塊把調(diào)試過程分解成幾個很自然的概念:調(diào)試者(debugger)和被調(diào)試者(debuggee),以及他們中間的通信器。被調(diào)試者運行于我們想調(diào)試的?Java?虛擬機之上,它可以通過?JVMTI?這個標準接口,監(jiān)控當前虛擬機的信息;調(diào)試者定義了用戶可使用的調(diào)試接口,通過這些接口,用戶可以對被調(diào)試虛擬機發(fā)送調(diào)試命令,同時調(diào)試者接受并顯示調(diào)試結(jié)果。在調(diào)試者和被調(diào)試著之間,調(diào)試命令和調(diào)試結(jié)果,都是通過?JDWP?的通訊協(xié)議傳輸?shù)?。所有的命令被封裝成?JDWP?命令包,通過傳輸層發(fā)送給被調(diào)試者,被調(diào)試者接收到?JDWP?命令包后,解析這個命令并轉(zhuǎn)化為?JVMTI?的調(diào)用,在被調(diào)試者上運行。類似的,JVMTI?的運行結(jié)果,被格式化成?JDWP?數(shù)據(jù)包,發(fā)送給調(diào)試者并返回給?JDI?調(diào)用。而調(diào)試器開發(fā)人員就是通過?JDI?得到數(shù)據(jù),發(fā)出指令。圖?2?展示了這個過程:
7.2.1.1.1.?圖?2.?JPDA?模塊層次
?
當然,開發(fā)人員完全可以不使用完整的三個層次,而是基于其中的某一個層次開發(fā)自己的應(yīng)用。比如您完全可以僅僅依靠通過?JVMTI?函數(shù)開發(fā)一個調(diào)試工具,而不使用?JDWP?和?JDI,只使用自己的通訊和命令接口。當然,除非是有特殊的需求,利用已有的實現(xiàn)會使您事半功倍,避免重復(fù)發(fā)明輪子。
這三個模塊我們會在后續(xù)文章中分別詳細介紹,這里我們簡單介紹它們的主要功能:
?
7.3.?JVMTI?的簡介
JVMTI(JVM?Tool?Interface)是?Java?虛擬機所提供的?native?編程接口,是?JVMPI(Java?Virtual?Machine?Profiler?Interface)和?JVMDI(Java?Virtual?Machine?Debug?Interface)的更新版本。從這個?API?的發(fā)展歷史軌跡中我們就可以知道,JVMTI?提供了可用于?debug?和?profiler?的接口;同時,在?Java?5/6?中,虛擬機接口也增加了監(jiān)聽(Monitoring),線程分析(Thread?analysis)以及覆蓋率分析(Coverage?Analysis)等功能。正是由于?JVMTI?的強大功能,它是實現(xiàn)?Java?調(diào)試器,以及其它?Java?運行態(tài)測試與分析工具的基礎(chǔ)。
JVMTI?并不一定在所有的?Java?虛擬機上都有實現(xiàn),不同的虛擬機的實現(xiàn)也不盡相同。不過在一些主流的虛擬機中,比如?Sun?和?IBM,以及一些開源的如?Apache?Harmony?DRLVM?中,都提供了標準?JVMTI?實現(xiàn)。
JVMTI?是一套本地代碼接口,因此使用?JVMTI?需要我們與?C/C++?以及?JNI?打交道。事實上,開發(fā)時一般采用建立一個?Agent?的方式來使用?JVMTI,它使用?JVMTI?函數(shù),設(shè)置一些回調(diào)函數(shù),并從?Java?虛擬機中得到當前的運行態(tài)信息,并作出自己的判斷,最后還可能操作虛擬機的運行態(tài)。把?Agent?編譯成一個動態(tài)鏈接庫之后,我們就可以在?Java?程序啟動的時候來加載它(啟動加載模式),也可以在?Java?5?之后使用運行時加載(活動加載模式)。
·?-agentlib:agent-lib-name=options
·?-agentpath:path-to-agent=options
?
?
7.4.?Agent?的工作過程
7.4.1.?啟動
Agent?是在?Java?虛擬機啟動之時加載的,這個加載處于虛擬機初始化的早期,在這個時間點上:
·?所有的?Java?類都未被初始化;
·?所有的對象實例都未被創(chuàng)建;
·?因而,沒有任何?Java?代碼被執(zhí)行;
但在這個時候,我們已經(jīng)可以:
·?操作?JVMTI?的?Capability?參數(shù);
·?使用系統(tǒng)參數(shù);
動態(tài)庫被加載之后,虛擬機會先尋找一個?Agent?入口函數(shù):
JNIEXPORT?jint?JNICALL?Agent_OnLoad(JavaVM?*vm,?char?*options,?void?*reserved)
在這個函數(shù)中,虛擬機傳入了一個?JavaVM?指針,以及命令行的參數(shù)。通過?JavaVM,我們可以獲得?JVMTI?的指針,并獲得?JVMTI?函數(shù)的使用能力,所有的?JVMTI?函數(shù)都通過這個?jvmtiEnv?獲取,不同的虛擬機實現(xiàn)提供的函數(shù)細節(jié)可能不一樣,但是使用的方式是統(tǒng)一的。
jvmtiEnv?*jvmti;?
(*jvm)->GetEnv(jvm,?&jvmti,?JVMTI_VERSION_
7.5.?JVMTI?基本功能
JVMTI?的功能非常豐富,包含了虛擬機中線程、內(nèi)存?/?堆?/?棧,類?/?方法?/?變量,事件?/?定時器處理等等?20?多類功能,下面我們介紹一下,并舉一些簡單列子。
7.5.1.?事件處理和回調(diào)函數(shù)
從上文我們知道,使用?JVMTI?一個基本的方式就是設(shè)置回調(diào)函數(shù),在某些事件發(fā)生的時候觸發(fā)并作出相應(yīng)的動作。因此這一部分的功能非?;?,當前版本的?JVMTI?提供了許多事件(Event)的回調(diào),包括虛擬機初始化、開始運行、結(jié)束,類的加載,方法出入,線程始末等等。如果想對這些事件進行處理,我們需要首先為該事件寫一個函數(shù),然后在?jvmtiEventCallbacks?這個結(jié)構(gòu)中指定相應(yīng)的函數(shù)指針。比如,我們對線程啟動感興趣,并寫了一個?HandleThreadStart?函數(shù),那么我們需要在?Agent_OnLoad?函數(shù)里加入:
?
7.5.2.?內(nèi)存控制和對象獲取
內(nèi)存控制是一切運行態(tài)的基本功能。?JVMTI?除了提供最簡單的內(nèi)存申請和撤銷之外(這塊內(nèi)存不受?Java?堆管理,開發(fā)人員需要自行進行清理工作,不然會造成內(nèi)存泄漏),也提供了對?Java?堆的操作。眾所周知,Java?堆中存儲了?Java?的類、對象和基本類型(Primitive),通過對堆的操作,開發(fā)人員可以很容易的查找任意的類、對象,甚至可以強行執(zhí)行垃圾收集工作。?JVMTI?中對?Java?堆的操作與眾不同,它沒有提供一個直接獲取的方式(由此可見,虛擬機對對象的管理并非是哈希表,而是某種樹?/?圖方式),而是使用一個迭代器(iterater)的方式遍歷:
7.5.3.?線程和鎖
線程是?Java?運行態(tài)中非常重要的一個部分,在?JVMTI?中也提供了很多?API?進行相應(yīng)的操作,包括查詢當前線程狀態(tài),暫停,恢復(fù)或者終端線程,還可以對線程鎖進行操作。開發(fā)者可以獲得特定線程所擁有的鎖:
jvmtiError?GetOwnedMonitorInfo(jvmtiEnv*?env,?
????jthread?thread,?
????jint*?owned_monitor_count_ptr,?
????jobject**?owned_monitors_ptr)
也可以獲得當前線程正在等待的鎖:
jvmtiError?GetCurrentContendedMonitor(jvmtiEnv*?env,?
????jthread?thread,?
????jobject*?monitor_ptr)
?
7.5.4.?調(diào)試功能
調(diào)試功能是?JVMTI?的基本功能之一,這主要包括了設(shè)置斷點、調(diào)試(step)等,在?JVMTI?里面,設(shè)置斷點的?API?本身很簡單:
jvmtiError?SetBreakpoint(jvmtiEnv*?env,?
????jmethodID?method,?
????jlocation?location)
?
7.6.?主要部分
7.6.1.?Java?虛擬機工具接口(JVMTI)
JVMTI(Java?Virtual?Machine?Tool?Interface)即指?Java?虛擬機工具接口,它是一套由虛擬機直接提供的?native?接口,它處于整個?JPDA?體系的最底層,所有調(diào)試功能本質(zhì)上都需要通過?JVMTI?來提供。通過這些接口,開發(fā)人員不僅調(diào)試在該虛擬機上運行的?Java?程序,還能查看它們運行的狀態(tài),設(shè)置回調(diào)函數(shù),控制某些環(huán)境變量,從而優(yōu)化程序性能。我們知道,JVMTI?的前身是?JVMDI?和?JVMPI,它們原來分別被用于提供調(diào)試?Java?程序以及?Java?程序調(diào)節(jié)性能的功能。在?J2SE?5.0?之后?JDK?取代了?JVMDI?和?JVMPI?這兩套接口,JVMDI?在最新的?Java?SE?6?中已經(jīng)不提供支持,而?JVMPI?也計劃在?Java?SE?7?后被徹底取代。
7.6.2.?Java?調(diào)試線協(xié)議(JDWP)
JDWP(Java?Debug?Wire?Protocol)是一個為?Java?調(diào)試而設(shè)計的一個通訊交互協(xié)議,它定義了調(diào)試器和被調(diào)試程序之間傳遞的信息的格式。在?JPDA?體系中,作為前端(front-end)的調(diào)試者(debugger)進程和后端(back-end)的被調(diào)試程序(debuggee)進程之間的交互數(shù)據(jù)的格式就是由?JDWP?來描述的,它詳細完整地定義了請求命令、回應(yīng)數(shù)據(jù)和錯誤代碼,保證了前端和后端的?JVMTI?和?JDI?的通信通暢。比如在?Sun?公司提供的實現(xiàn)中,它提供了一個名為?jdwp.dll(jdwp.so)的動態(tài)鏈接庫文件,這個動態(tài)庫文件實現(xiàn)了一個?Agent,它會負責解析前端發(fā)出的請求或者命令,并將其轉(zhuǎn)化為?JVMTI?調(diào)用,然后將?JVMTI?函數(shù)的返回值封裝成?JDWP?數(shù)據(jù)發(fā)還給后端。
另外,這里需要注意的是?JDWP?本身并不包括傳輸層的實現(xiàn),傳輸層需要獨立實現(xiàn),但是?JDWP?包括了和傳輸層交互的嚴格的定義,就是說,JDWP?協(xié)議雖然不規(guī)定我們是通過?EMS?還是快遞運送貨物的,但是它規(guī)定了我們傳送的貨物的擺放的方式。在?Sun?公司提供的?JDK?中,在傳輸層上,它提供了?socket?方式,以及在?Windows?上的?shared?memory?方式。當然,傳輸層本身無非就是本機內(nèi)進程間通信方式和遠端通信方式,用戶有興趣也可以按?JDWP?的標準自己實現(xiàn)。
7.6.3.?Java?調(diào)試接口(JDI)
JDI(Java?Debug?Interface)是三個模塊中最高層的接口,在多數(shù)的?JDK?中,它是由?Java?語言實現(xiàn)的。?JDI?由針對前端定義的接口組成,通過它,調(diào)試工具開發(fā)人員就能通過前端虛擬機上的調(diào)試器來遠程操控后端虛擬機上被調(diào)試程序的運行,JDI?不僅能幫助開發(fā)人員格式化?JDWP?數(shù)據(jù),而且還能為?JDWP?數(shù)據(jù)傳輸提供隊列、緩存等優(yōu)化服務(wù)。從理論上說,開發(fā)人員只需使用?JDWP?和?JVMTI?即可支持跨平臺的遠程調(diào)試,但是直接編寫?JDWP?程序費時費力,而且效率不高。因此基于?Java?的?JDI?層的引入,簡化了操作,提高了開發(fā)人員開發(fā)調(diào)試程序的效率。
表?1?總結(jié)了三個模塊的不同點:
7.6.3.1.1.?表?1.?JPDA?層次比較
?
模塊 |
層次 |
編程語言 |
作用 |
JVMTI |
底層 |
C |
獲取及控制當前虛擬機狀態(tài) |
JDWP |
中介層 |
C |
定義?JVMTI?和?JDI?交互的數(shù)據(jù)格式 |
JDI |
高層 |
Java |
提供?Java?API?來遠程控制被調(diào)試虛擬機 |
?
?
8.?找到源碼???this.m_jTotalEuros?=?new?JLabel();
????this.m_jLblTotalEuros1?=?new?JLabel();
this.m_jSubtotalEuros?=?new?JLabel();
?
?
參考
深入?Java?調(diào)試體系,第?2?部分??JVMTI?和?Agent?實現(xiàn).htm
JVM源碼分析之javaagent原理完全解讀.htm
?
本文摘自 :https://blog.51cto.com/a