posts - 42,comments - 83,trackbacks - 0
                JPDA(Java Platform Debugger Architecture)是sun推出的一套工具接口,有了這些接口,debugger、profile工具可以attach到target JVM,進(jìn)而可以監(jiān)控、調(diào)試我們的程序。JPDA包括三部分:JVM TI, JDI, JDWP。TI可以使用native語言,通過調(diào)用jvmti.c提供的系列庫函數(shù),實(shí)現(xiàn)debug工作,而JDI是TI面向Java開發(fā)人員提供的高層開發(fā)接口。TI代替了早期的DI,每個(gè)版本都做了一定的功能增強(qiáng)。隨著JDK的發(fā)展,JPDA變得越發(fā)強(qiáng)大,比如thread信息檢查、method調(diào)用跟蹤、memory walk-through、perm內(nèi)存區(qū)檢查等,有了這些接口,我們完全可以自己造出類似于:jhat、jmap、jstack、jconsole這樣的車子。用一句過時(shí)話來說:JPDA,很好很強(qiáng)大。

                  在Weblogic中,我們通常能看到像下面這樣的警告信息:
          BEA-000337 Feb 1, 2007 11:01:05 AM EST Error WebLogicServer ExecuteThread: '14' for queue: 'weblogic.kernel.Default' has been busy for "72" seconds working on the request "connection82.session95", which is more than the configured time (StuckThreadMaxTime) of "60" seconds.

                   這樣的信息只是一個(gè)提示,告訴最終用戶某個(gè)執(zhí)行線程執(zhí)行了多長時(shí)間(只有執(zhí)行時(shí)間超過StuckThread-MaxTime,默認(rèn)600秒),用戶可以根據(jù)這些信息,分析對(duì)應(yīng)的請(qǐng)求執(zhí)行了這么長時(shí)間是否正常,如果在預(yù)期或可以接受范圍內(nèi),不用作任何干預(yù),否則我們需要借助于thread dump分析執(zhí)行時(shí)間的瓶頸。出現(xiàn)這樣的警告信息,weblogic不會(huì)對(duì)這樣的線程作任何操作(weblogic無法識(shí)別這么長的執(zhí)行時(shí)間是不是用戶所預(yù)期的,比如報(bào)表操作、文件傳輸?shù)缺旧砜赡芫秃芎臅r(shí)),直到線程結(jié)束。線程能執(zhí)行結(jié)束還好,如果是死鎖呢? 這樣的線程會(huì)一直被掛著,直到weblogic重啟。重啟對(duì)于很多生產(chǎn)系統(tǒng)而言是最后的選擇,那么我們有什么方法來避免重啟呢? Weblogic9以后,線程管理方面work manager代替了早期的thread pool,而且work manager提供了stuck thread的管理,比如出現(xiàn)幾個(gè)stuck thread后,我們可以要求work manager停止應(yīng)用,避免更多的線程被stuck。weblogic停止應(yīng)用只是不提供服務(wù),但還是不會(huì)影響正在執(zhí)行的線程。

                   曾經(jīng)不止一次的被客戶問道我們能否中斷這樣的線程,從weblogic層面來看,這是mission impossible。現(xiàn)在有了TI,我們可以通過它中斷這樣的線程。

                    要中斷這樣的線程,首先要借助thread dump拿到線程名,我們將以線程名為filter。Thread dump信息如下:

          "[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'" daemon prio=6 tid=0x2b25a800 nid=0x3c0 waiting on condition [0x2e08f000..0x2e08fa14]
           java.lang.Thread.State: TIMED_WAITING (sleeping)
                at java.lang.Thread.sleep(Native Method)
                ......
          上面這個(gè)線程的名字就是:[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'

                   為了能正確的attach上JVM,啟動(dòng)的時(shí)候需要加上如下的JAVA_OPTIONS,
                   -Xdebug -Xrunjdwp:transport=dt_socket,address=9191,server=y,suspend=n

                   現(xiàn)在我們就可以下面的方法attach到target JVM,
           1     private VirtualMachine connectVM(){
           2             VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
           3             List connectors = vmm.attachingConnectors();
           4             Connector conn = null;
           5             AttachingConnector socketAttachingConnector = null
           6             /*
           7             * host and port should be set here
           8             */
           9             .
          10       try{
          11           vm = socketAttachingConnector.attach(arguments);
          12       }catch(Exception e){
          13           e.printStackTrace();
          14       }
          15       return this.vm;
          16     }

                  有了線程名、connection,我們就可以用下面的方法去中斷掛死線程了,
           1     public void terminateThread(String threadPattern){
           2         if(vm != null){
           3             List threads = vm.allThreads();
           4             ThreadReference tr = null;
           5             int loop = -1;
           6             for(loop=0; loop<threads.size(); loop++){
           7                 if(tr.toString().indexOf(threadPattern) != -1){
           8                     tr.interrupt();
           9                     System.out.println(threadPattern + " is terminated!");
          10                     break;
          11                 }
          12             }
          13             if(loop == threads.size())
          14                 System.out.println("no matched thread was found in target VM!");
          15         }
          16     }
                  
                  線程被中斷的時(shí)候,會(huì)收到InterruptedExcetpion,比如我在測(cè)試中讓線程sleep,然后利用上面的程序去中斷sleep,收到的異常如下:

          java.lang.InterruptedException: sleep interrupted
                  at java.lang.Thread.sleep(Native Method)
                  at test.jpda.clazz.Test2.run(Test2.java:14)
                  at test.jpda.clazz.Test1.run(Test1.java:10)
                  at test.jpda.clazz.Test.run(Test.java:9)
                  at jsp_servlet.__index._jspService(__index.java:91)
                  at weblogic.servlet.jsp.JspBase.service(JspBase.java:34)
                  at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
                  at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
                  at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
                  at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
                  at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.ru(WebAppServletContext.java:3498)
                  at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
                  at weblogic.security.service.SecurityManager.runAs(Unknown Source)
                  at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
                  at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
                  at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
                  at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
                  at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)       


          注意:線程名一定不能寫錯(cuò)啊,否則就可能誤殺了,老板批你別怨俺。

          posted on 2009-09-10 15:18 走走停停又三年 閱讀(5995) 評(píng)論(6)  編輯  收藏 所屬分類: Java Technology

          FeedBack:
          # re: JVM TI學(xué)習(xí)(1)----如何中斷weblogic中stuck thread
          2009-09-09 12:37 | Ken Wu
          你這類應(yīng)用其實(shí)還不算是TI的應(yīng)用范疇。
          真正的TI,是需要在vm啟動(dòng)階段就植入的。  回復(fù)  更多評(píng)論
            
          # re: JVM TI學(xué)習(xí)(1)----如何中斷weblogic中stuck thread
          2009-09-09 13:01 | 走走停停又三年
          你手里有TI的例子嗎?我對(duì)這塊比較感興趣,如果有能否共享一下? 你說的是agent吧,我這里用的是JDI,TI的Java接口。

          Tools can be written directly to JVM TI or indirectly through higher level interfaces. The Java Platform Debugger Architecture includes JVM TI, but also contains higher-level, out-of-process debugger interfaces. The higher-level interfaces are more appropriate than JVM TI for many tools. For more information on the Java Platform Debugger Architecture, see the Java Platform Debugger Architecture website.

          參考這個(gè)鏈接:http://java.sun.com/javase/6/docs/platform/jvmti/jvmti.html  回復(fù)  更多評(píng)論
            
          # re: JVM TI學(xué)習(xí)(1)----如何中斷weblogic中stuck thread
          2009-09-09 14:24 | JBahamut
          tr.interrupt()
          這個(gè)效果應(yīng)該和Thread.interrupt一樣吧,線程并沒有被終止  回復(fù)  更多評(píng)論
            
          # re: JVM TI學(xué)習(xí)(1)----如何中斷weblogic中stuck thread
          2009-09-09 14:45 | 走走停停又三年
          對(duì),線程不會(huì)被結(jié)束,等同于thread.interrupt()  回復(fù)  更多評(píng)論
            
          # re: JVM TI學(xué)習(xí)(1)----如何中斷weblogic中stuck thread
          2009-09-10 23:25 | Ken Wu
          @走走停停又三年
          你的文檔是對(duì)的,真正的TI一般用C++寫的,植入第三方agent libraries。
          比如替換Object.class之類的操作,如果你用instrumentation就實(shí)現(xiàn)不了。  回復(fù)  更多評(píng)論
            
          # re: JVM TI學(xué)習(xí)(1)----如何中斷weblogic中stuck thread
          2009-09-11 09:01 | 走走停停又三年
          不要太拘泥于定義。所謂TI,說白了就是工具接口,沒必要把要什么語言定義死吧,要這個(gè)語言寫就是,換個(gè)語言寫就不是。也許你是對(duì)的,TI用c或c++寫,而JDI,其實(shí)就是TI的高層接口,對(duì)于Java程序員更為適用。兩者的功能區(qū)別有多大? 他們的功能都依賴于JVM開放函數(shù),即jmvti.h中的函數(shù)。你用TI要限于這些函數(shù),而JDI就是對(duì)這些函數(shù)的封裝,我不覺得會(huì)少多少東西。至少我們常用的:heap遍歷、class裝載、卸載監(jiān)聽、方法調(diào)用監(jiān)聽、鎖等待監(jiān)聽等一一都有。至于類動(dòng)態(tài)更新,你可以看看:http://www.aygfsteel.com/fjin/archive/2009/09/11/294634.html  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 内江市| 英吉沙县| 江安县| 牡丹江市| 若尔盖县| 巴彦淖尔市| 北安市| 潜山县| 莱州市| 上饶县| 长汀县| 唐山市| 九寨沟县| 双峰县| 扎兰屯市| 万荣县| 仁怀市| 泽州县| 宜川县| 凭祥市| 永宁县| 南丰县| 都匀市| 陈巴尔虎旗| 翁源县| 香格里拉县| 永定县| 武平县| 全南县| 罗山县| 康定县| 德格县| 保山市| 鹤山市| 惠东县| 祁门县| 临安市| 台中市| 聂拉木县| 宝丰县| 台山市|