解析本地方法映射Java層的數(shù)據(jù)類型
前言
Java 語言上定義了不同的數(shù)據(jù)類型,比如有基礎(chǔ)類型int、double等等,還有所有類的父類Object等,這些都是 Java 層面的類型,而使用本地方法的處理過程需要有它們對應(yīng)的類型。
大概的流程
Java 層編寫的本地方法,被編譯器編譯為字節(jié)碼,字節(jié)碼將按照規(guī)范將不同類型的參數(shù)給記錄到 class 文件中,比如 B 表示 byte、I 表示 int、J 表示 long 等等。那么一個(gè)如下的本地方法,被記錄為(Ljava/lang/Object;II)V。
public static native void test(Object o, int i, int i2);
上述對應(yīng)的方法被注冊JVM中,當(dāng)執(zhí)行到調(diào)用本地方法時(shí)則會按照類型映射轉(zhuǎn)換成本地?cái)?shù)據(jù)類型,比如int->jint和Object->jobject。這里其實(shí) int 和 jint 在 C++ 中是一樣的,只是用 typedef 定義了另外一個(gè)名稱而已,而 jobject 是一個(gè)指針,執(zhí)行引擎在執(zhí)行 Java 層邏輯時(shí)生成了 Object 對象,它在 JVM 層有專門的數(shù)據(jù)結(jié)構(gòu),這里的 jobject 就是指向這個(gè)結(jié)構(gòu)的指針,在需要使用時(shí)可以強(qiáng)制轉(zhuǎn)換成 JVM 層的數(shù)據(jù)結(jié)構(gòu),然后即可對其進(jìn)行操作。另外,JVM 中用 oop 來表示對象指針。
基礎(chǔ)類型映射
| Java Type | Native Type | value |
|---|---|---|
| boolean | jboolean | true或false |
| byte | jbyte | -128~127 |
| short | jshort | -pow(2,15)~pow(2,15)-1 |
| int | jint | -pow(2,31)~pow(2,31)-1 |
| long | jlong | -pow(2,63)~pow(2,63)-1 |
| float | jfloat | IEEE754標(biāo)準(zhǔn)單精度浮點(diǎn)數(shù) |
| double | jdouble | IEEE754標(biāo)準(zhǔn)雙精度浮點(diǎn)數(shù) |
| char | jchar | 16位不帶符號,Unicode字符 |
引用類型映射
除了基礎(chǔ)的類型映射外,Java 層其他對象類型為引用類型,那么本地方法對應(yīng)的是 jobject 類型,另外,它還會派生出經(jīng)常用的一些子類,比如 jstring、jclass 等等,具體如下,
class _jobject {};
class _jclass : public _jobject {};
class _jthrowable : public _jobject {};
class _jstring : public _jobject {};
class _jarray : public _jobject {};
class _jbooleanArray : public _jarray {};
class _jbyteArray : public _jarray {};
class _jcharArray : public _jarray {};
class _jshortArray : public _jarray {};
class _jintArray : public _jarray {};
class _jlongArray : public _jarray {};
class _jfloatArray : public _jarray {};
class _jdoubleArray : public _jarray {};
class _jobjectArray : public _jarray {};
可以看到定義了_jobject類,該類為空類,而其他的類包括_jclass _jthrowable _jstring _jarray都是繼承_jobject類。此外,數(shù)組類型還派生出了9個(gè)子類,分別對應(yīng)基礎(chǔ)類型數(shù)組和引用類型數(shù)組。
前面定義完類后再定義指針別名,這里的就是本地方法的類型了。另外,這些都是 C++ 的定義,如果是 C 編譯器則會使用 struct 來定義 _jobject,而非 class。
typedef _jobject *jobject; typedef _jclass *jclass; typedef _jthrowable *jthrowable; typedef _jstring *jstring; typedef _jarray *jarray; typedef _jbooleanArray *jbooleanArray; typedef _jbyteArray *jbyteArray; typedef _jcharArray *jcharArray; typedef _jshortArray *jshortArray; typedef _jintArray *jintArray; typedef _jlongArray *jlongArray; typedef _jfloatArray *jfloatArray; typedef _jdoubleArray *jdoubleArray; typedef _jobjectArray *jobjectArray;
CPP的空類
上面的引用類型定義為空類,這里了解下C++的空類,通常我們要定義一個(gè)空類可以如下兩種方式,
class Empty{}
struct Empty{}
經(jīng)過上述定義后的空類,它的大小為1,但是一個(gè)空類啥都沒有的話它有什么用呢?其實(shí)它可以用來區(qū)分不同的對象,空類定義的不同對象擁有不同的地址,使用new操作出來的對象也有不同的指針,而且空類也能區(qū)分不同的類別。
指針轉(zhuǎn)換
所以有了這些類型映射后我們是怎么聯(lián)系起來使用的呢?其實(shí)很簡單,答案就是進(jìn)行指針轉(zhuǎn)換,前面提到過 Java 層的對象在 JVM 中是有一定的數(shù)據(jù)結(jié)構(gòu)的,即用 oop 來表示對象指針,那么 jobject 可以作如下轉(zhuǎn)換,其中 handle 即為 jobject 類型。
oop result = *reinterpret_cast<oop*>(handle);
轉(zhuǎn)換成 oop 后要進(jìn)一步處理就很方便了,比如想要獲取一些類相關(guān)的元數(shù)據(jù)時(shí)可以使用其中的 klass 來獲取。
總結(jié)
以上,Java 層定義的類型在本地方法有著與之相對應(yīng)的數(shù)據(jù)類型,而且 Java 層源碼被編譯為字節(jié)碼后保存了本地方法參數(shù)對應(yīng)的類型,JVM 執(zhí)行時(shí)可以根據(jù)不同的類型轉(zhuǎn)換成本地方法對應(yīng)的類型,而本地方法定義的類型都為空類,主要作用是用來綁定對象,并且可以區(qū)分對象類型,在必要時(shí)刻通過指針轉(zhuǎn)換即可訪問對象或類元數(shù)據(jù)。
- Java編碼輔助工具M(jìn)apstruct用法詳解
- MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法
- Java Map.get()返回指定鍵所映射的值
- Java HashSet(散列集),HashMap(散列映射)的簡單介紹
- Java中具有映射關(guān)系的容器:數(shù)組和Map的區(qū)別說明
- Java底層基于鏈表實(shí)現(xiàn)集合和映射--集合Set操作詳解
- Java實(shí)現(xiàn)鼠標(biāo)模擬與鍵盤映射
- javaMybatis映射屬性,高級映射詳解
- java 中MyBatis注解映射的實(shí)例詳解
- Java MapStruct解了對象映射的毒
相關(guān)文章
Java使用PreparedStatement接口及ResultSet結(jié)果集的方法示例
這篇文章主要介紹了Java使用PreparedStatement接口及ResultSet結(jié)果集的方法,結(jié)合實(shí)例形式分析了PreparedStatement接口及ResultSet結(jié)果集的相關(guān)使用方法與操作注意事項(xiàng),需要的朋友可以參考下2018-07-07
Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限的示例代碼
在我們?nèi)粘i_發(fā)過程中,通常會涉及到數(shù)據(jù)權(quán)限問題,本文主要介紹了Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
SpringMVC @RequestBody屬性名大寫字母注入失敗的解決
這篇文章主要介紹了SpringMVC @RequestBody屬性名大寫字母注入失敗的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Spring Data Jpa 自動(dòng)生成表結(jié)構(gòu)的方法示例
這篇文章主要介紹了Spring Data Jpa 自動(dòng)生成表結(jié)構(gòu)的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
Java通過匿名類來實(shí)現(xiàn)回調(diào)函數(shù)實(shí)例總結(jié)
這篇文章主要介紹了Java通過匿名類來實(shí)現(xiàn)回調(diào)函數(shù)的例子,回調(diào)函數(shù)就是一種函數(shù)簽名(若干個(gè)輸入?yún)?shù)、一個(gè)輸出參數(shù))的規(guī)范,java雖不存在函數(shù)聲明,但是java可以用接口來強(qiáng)制規(guī)范。具體操作步驟大家可查看下文的詳細(xì)講解,感興趣的小伙伴們可以參考一下。2017-08-08

