Java方法簽名與JNI,反射

http://blog.houzhi.me/2016/03/19/java-signature-reflect-jni

在這段時間寫東西,必須要先吐槽一下找實習的杯具。找個實習不容易,沒經驗,各種跪。

一直都覺得在Java反射中,那些反射的方法調用都很有規律,每一個調用都需要相同的特性:函數對象(Method),函數參數,類對象。今天坐在電腦前又回憶了JNI的調用方式(C++調用Java),也需要相同的內容:函數ID(jmethodID),參數,類對象(jobject),JNIEnv。仔細一比較,其實兩者就是一樣的,都是Java方法簽名

記得剛學Java的時候,也有特別將Java方法簽名,那時候就基本是記下了,但是根本沒想到Java方法簽名意味着什麼,現在終於是能深切體會一些了。這個簽名就表示了Java方法,相當於它的ID,適用於Java整個環境,能夠通過指定這些內容,形容一次函數調用。我們平時採用普通方式調用Java函數,其實也就是先描述了函數,參數,類對象。其實在Java層,我覺得可以理解爲隱含了一個線程描述(JVM)。在native裏面,就有個JNIEnv(線程本地變量)描述一個Java虛擬機環境。至於到了java的.class文件裏面也是一樣的包含了這些標誌。下面是截取了一段Constant poll中的內容,裏面指定了類StringBuilder,方法參數String,

#12 = Methodref          #7.#55         //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

下面是.class文件方法段裏面的stack代碼,

21: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

只是感性的認識,如果把全部的.class 文件通過javap -verbose 的內容都貼上來,實在太囧了。對於invokevirtual命令可以參考這裏的http://book.51cto.com/art/200906/131732.htm。如果想要了解,需要對虛擬機指令的操作方式有所瞭解,那個東東跟彙編有點類似。

關於java方法簽名,官網上面有介紹java method signatures。Java的方法聲明具有下面幾個組件:

  1. 訪問標誌(public,private…)
  2. 返回類型
  3. 方法名
  4. 參數列表
  5. 異常表
  6. 方法體

但是Java方法中真正被判斷是否是同一個方法的簽名與上面是不一致的,就像我們熟知的方法重載一樣。正如method signatures 所說,它在內部真正具體標記意義的是方法名稱和參數列表,因爲這種都是在同一個類裏面講重載的,真正算起來應該還要加上具體的類方法,以及具體JVM線程。所以JNI和反射的調用其實就是指定了函數實際的標記:JVM,類對象,方法ID(Method,jmethodID),參數列表。

所以如果需要對各種方式的Java調用進行完全的認識,就需要熟記Java這幾種簽名標記的特性。如果在實際編碼過程中,想要去調用一個方法,那麼一定要獲取對應的對象,方法名,方法參數。如果是可能存在不同的虛擬機環境,那還得加上虛擬機環境的標記(類似JNIEnv)。當然C/C++的虛擬機中,由於C/C++中int,Object並沒有統一父對象,C/C++ JNI提供了針對不同的返回類型,對應不同的調用函數。


好好學習

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章