<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    Clojure世界:利用HouseMD診斷clojure

    Posted on 2012-06-15 02:52 dennis 閱讀(12163) 評論(2)  編輯  收藏 所屬分類: Clojure工具和命令

        HouseMD是淘寶的聚石寫的一個非常優(yōu)秀的Java進(jìn)程運行時診斷和調(diào)試工具,如果你接觸過btrace,那么HouseMD也許你應(yīng)該嘗試下,它比btrace更易用,不需要寫腳本,類似strace的方式attach到j(luò)vm進(jìn)程做跟蹤調(diào)試。

        基本的安裝和使用請看這篇文檔《UserGuide》,恕不重復(fù)。以下內(nèi)容都假設(shè)你正確安裝了housemd。

        本文主要介紹下怎么用housemd診斷跟蹤clojure進(jìn)程。Clojure的java實現(xiàn)也是跑在JVM里,當(dāng)然也可以用housemd。

        我們以一個簡單的例子開始,假設(shè)我們有如下clojure代碼:
    (loop [x 1]
      (Thread/sleep 1000)
      (prn x)
      (recur (inc x)))

        這段很簡單,只是間隔一秒不斷地打印遞增的數(shù)字x。我們準(zhǔn)備用housemd跟蹤這個程序的運行,首先運行這個程序,你可以用lein,也可以直接java命令運行:
    java -cp clojure.jar clojure.main test.clj

        運行時不斷地在控制臺打印數(shù)字,通過jps或者ps查詢到該進(jìn)程的id,假設(shè)為pid,使用housemd連接到該進(jìn)程:
    housemd <pid>
        順利進(jìn)入housemd的交互控制臺,通過help命令可以查詢支持的命令:

    housemd> help

    quit      terminate the process.
    help      display this infomation.
    trace     display or output infomation of method invocaton.
    loaded    display loaded classes information.

        要用housemd調(diào)試clojure,你需要對clojure的實現(xiàn)有一點點了解,有興趣可以看過去的一篇blog《clojure hacking guide》,簡單來說,clojure的編譯器會將clojure代碼編譯成java類并運行。對于JVM來說,clojure生成的類,跟java編譯器生成類沒有什么不同。
        具體到上面的clojure代碼,會生成一個名為user$eval1的類,user是默認(rèn)的namespace,而eval1是clojure編譯器自動生成的一個標(biāo)示類名,通過loaded命令查詢類的加載情況:
    housemd> loaded user$eval1 -h
    user$eval1 -> null
        - clojure.lang.DynamicClassLoader@1d25d06e
            - clojure.lang.DynamicClassLoader@1d96f4b5
                - sun.misc.Launcher$AppClassLoader@a6eb38a
                    - sun.misc.Launcher$ExtClassLoader@69cd2e5f

        通過-h選項打印了加載user$eval1的類加載器的層次關(guān)系,因為user$eval1是動態(tài)生成的(clojure啟動過程中),因此它不在任何一個class或者jar文件中。除了查詢user namespace的類之外,你還可以查詢clojure.core,clojure.lang,clojure.java等任何被加載進(jìn)來的類,例如查詢clojure.core.prn的類,在clojure里這是一個函數(shù),在jvm看來這只是一個類:
    housemd> loaded -h core$prn
    clojure.core$prn -> /Volumes/HDD/Users/apple/clojure/clojure.jar
        - sun.misc.Launcher$AppClassLoader@a6eb38a
            - sun.misc.Launcher$ExtClassLoader@69cd2e5f
       注意,不需要完整的namespace——clojure.core,直接core$prn即可。其他也是類似。小技巧:如果你實在不知道clojure編譯器生成的類名,你可以利用jvm自帶的jmap命令來查詢。

       接下來,我們嘗試用trace命令跟蹤方法的運行,例如例子中的clojure代碼用到了loop和recur兩個sepcial form,我們跟蹤下loop:
    housemd> trace -t 5 core$loop
    INFO : probe class clojure.core$loop
    core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
    core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

    core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
    core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

    core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
    core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

    core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
    core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

    core$loop.doInvoke(Object, Object, Object, Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null
    core$loop.getRequiredArity()                          sun.misc.Launcher$AppClassLoader@a6eb38a            0            -ms    null

    INFO : Ended by timeout
    INFO : reset class clojure.core$loop

        在5秒內(nèi),clojure.core$loop類有兩個方法各被調(diào)用了5次,doInvoke是實際的調(diào)用,而getRequiredArity用來查詢loop所需要的參數(shù)個數(shù)。trace還可以跟蹤到具體的方法,例如我們跟蹤prn函數(shù)的調(diào)用情況:
    housemd> trace -t 5 core$prn.doInvoke
    INFO : probe class clojure.core$prn
    core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            1            1ms    clojure.core$prn@3e4ac866

    core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            2           <1ms    clojure.core$prn@3e4ac866

    core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            3           <1ms    clojure.core$prn@3e4ac866

    core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            4           <1ms    clojure.core$prn@3e4ac866

    core$prn.doInvoke(Object)    sun.misc.Launcher$AppClassLoader@a6eb38a            5           <1ms    clojure.core$prn@3e4ac866

    INFO : Ended by timeout
    INFO : reset class clojure.core$prn
      
       trace打印了方法的調(diào)用次數(shù)(5秒內(nèi))和每次調(diào)用的時間(毫秒級別),以及調(diào)用的target object。小技巧:沒有可變參數(shù)的函數(shù)生成類最終調(diào)用的是invoke方法(參數(shù)個數(shù)可能重載),有可變參數(shù)的函數(shù)調(diào)用的是doInvoke方法。

       trace命令還支持打印調(diào)用堆棧到文件,例如:
    trace -t 5 -d -s  core$prn.doInvoke

       利用-s和-d命令會將詳細(xì)的調(diào)用信息輸出到臨時目錄,臨時目錄的路徑可以通過trace help命令查詢到,在我的機器上是/tmp/trace/<pid>@host目錄下。調(diào)用堆棧的輸出類似:
    example$square.invoke(Long) call by thread [main]
        example$eval9.invoke(test.clj:11)
        clojure.lang.Compiler.eval(Compiler.java:6465)
        clojure.lang.Compiler.load(Compiler.java:6902)
        clojure.lang.Compiler.loadFile(Compiler.java:6863)
        clojure.main$load_script.invoke(main.clj:282)
        clojure.main$script_opt.invoke(main.clj:342)
        clojure.main$main.doInvoke(main.clj:426)
        clojure.lang.RestFn.invoke(RestFn.java:421)
        clojure.lang.Var.invoke(Var.java:405)
        clojure.lang.AFn.applyToHelper(AFn.java:163)
        clojure.lang.Var.applyTo(Var.java:518)
        clojure.main.main(main.java:37)

       上面這個簡單的例子展示了使用housemd跟蹤診斷clojure進(jìn)程的方法。

       自定義ns和函數(shù)的調(diào)試與此類似,假設(shè)我們有下面的clojure代碼:
    (ns example)
    (defn square [x]
      (* x x))

    (loop [x 1]
      (Thread/sleep 1000)
      (square x)
      (recur (inc x)))
     
       ns為example,自定義函數(shù)square并定期循環(huán)調(diào)用。使用housemd診斷這段代碼:
    loaded -h example$square     #查詢square的加載情況
    trace -t 10 -d -s example$square.invoke  #跟蹤10秒內(nèi)square的調(diào)用情況

    評論

    # re: Clojure世界:利用HouseMD診斷clojure  回復(fù)  更多評論   

    2012-06-15 12:17 by ppt模板下載
    java 東西真是難理解 不過大型網(wǎng)站很多用這個的

    # re: Clojure世界:利用HouseMD診斷clojure  回復(fù)  更多評論   

    2014-09-02 09:17 by 好鄰居官網(wǎng)
    這個塊看看就好了,不是非常能看懂!
    主站蜘蛛池模板: 亚洲精品综合一二三区在线 | 精品国产一区二区三区免费| 亚洲成AV人片在WWW色猫咪| 777成影片免费观看| 亚洲大码熟女在线观看| 亚洲欧洲日产国码无码久久99| 久久福利资源网站免费看| 免费无码一区二区| 亚洲综合激情九月婷婷| vvvv99日韩精品亚洲| 2015日韩永久免费视频播放| 暖暖免费中文在线日本| 亚洲国产成人九九综合| 国产国拍亚洲精品福利| 成年女人免费视频播放体验区| 免费在线观影网站| 国产精品亚洲专区无码不卡| 亚洲第一成年网站大全亚洲| 久久久久国产亚洲AV麻豆 | 亚洲熟妇AV一区二区三区浪潮 | 国产免费观看a大片的网站| 午夜免费福利视频| 曰批全过程免费视频观看免费软件| 亚洲视频在线观看网址| 中文字幕亚洲专区| 天天拍拍天天爽免费视频| 久久久久久久岛国免费播放| 看全免费的一级毛片| 亚洲AV无码一区二区三区人 | 午夜性色一区二区三区免费不卡视频| 成年网在线观看免费观看网址 | 99精品视频在线观看免费| 午夜亚洲WWW湿好爽| 亚洲av成人一区二区三区| 精品久久久久久亚洲| 亚洲国产aⅴ综合网| 好吊妞视频免费视频| 国产成人yy免费视频| 美女内射无套日韩免费播放| 巨胸喷奶水www永久免费| 国产成人综合亚洲|