1. 程式人生 > >從Object.wat()方法看JNI及native方法底層呼叫邏輯

從Object.wat()方法看JNI及native方法底層呼叫邏輯

前言

早上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的建立和執行 這篇文章。