前言
早上debug join方法的時候,其内部調用wait方法,wait是Object中的native方法,但是在ClassLoader類中的findNative中打斷點,不會進去斷點。然後想了一下,是不是因為Object是Bootstrap類加載器加載的原因。
那麼怎麼才能知道native調用的到底是什麼方法呢?在網上搜尋"Java如何檢視native方法的實作",沒有搜到可用的内容。
索性自己去翻一下hostspot jdk的源碼,我下載下傳的是openjdk-8u40-src-b25-10_feb_2015.zip,可以從openjdk官網下載下傳。
舉個例子,比如我要搜尋Object中的wait方法:
1、openjdk目錄結構分析(有助于快速定位源碼位置)
請原諒我眼花缭亂的框選,打開Object.c看看:
2、初見Object.c
從wait方法入口進去,實作在jvm.cpp中
JDK中用到的jni接口,最終都會在jvm.h檔案中定義,并在jvm.cpp中作為C++實作的入口,也就是說jvm.cpp是Java世界和JVM中C++世界溝通的橋梁。
JVMWrapper("JVM_MonitorWait");這一句是定義了一個宏
看一下270行,我搜了下Histogram的意思,是直方圖,猜測這裡隻是在做JVM統計,或者為了監控而調用的邏輯。這裡先略過。
2.1 使用oop指針指向Java對象
接着看這行:
是把目前執行的java類包裝成一個Handle類型,Handle類型,見下圖,将Java對象指派給了一個oop指針類型。
2.2 緊接着這行:JvmtiExport::should_post_monitor_wait(),553行
should_post_monitor_wait預設false,在jvmtiEventController.cpp中的recompute_enabled方法中會進行設定,搜了下recompute_enabled在jvmtiEventController.cpp有多處調用,從名字上看可能有事件驅動的邏輯,should_post_monitor_wait的值應該也是響應時間設定的。
有哪些事件?導緻wait方法的這個should_post_monitor_wait變量變化的是哪些事件?
在Java中通過JNI接口可以實作Java調用本地方法;通過JVMTI接口可以實作在C++空間調用Java對象的方法。
jvmtiEventController.cpp中的recompute_enabled的部分方法體:
再看JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);這行。
小結:
寫的好亂,很多細節沒怎麼懂,看了if語句塊中的注釋,這段的意思是:目前線程已經擁有螢幕,但是沒被加到等待隊列中,JVMTI_EVENT_MONITOR_WAIT事件沒辦法處理unpark(),意思應該就是沒辦法釋放鎖。
那post_monitor_wait這個意思應該就是推遲螢幕的等待,就是先不釋放鎖。
2.3 接着看ObjectSynchronizer::wait(obj, ms, CHECK);
這個調用的實作在synchronizer.cpp檔案中,
1)首先,如果UseBiasedLocking為true,使用偏向鎖
2)如果millis < 0,抛出異常
3)inflate()中是鎖膨脹更新邏輯
4)調用objectMonitor.cpp中的wait方法。wait的大部分邏輯在這裡。可以參見延伸閱讀[1]
總結:
本文通過介紹openjdk底層源碼的目錄結構,wait方法執行涉及到的調用關系。對從Java方法調用到C++代碼調用有一個感性的認識。具體C++代碼邏輯,還需要進一步分析。
延伸閱讀:
[1] JVM源碼分析之Object.wait/notify實作
[2] 并發程式設計的藝術
[3] 源碼分析:Java中的Thread的建立和運作
關于搜尋技巧:
文章開頭提到,在網上搜尋"Java如何檢視native方法的實作",沒有搜到可用的内容。然後在看源碼的過程中,看到C++代碼裡的這個方法JVMWrapper。不是很明白,就去搜狗微信上搜尋了JVMWrapper。
搜尋到了源碼分析:Java中的Thread的建立和運作 這篇文章。