解析本地方法映射Java層的數(shù)據(jù)類(lèi)型
前言
Java 語(yǔ)言上定義了不同的數(shù)據(jù)類(lèi)型,比如有基礎(chǔ)類(lèi)型int、double等等,還有所有類(lèi)的父類(lèi)Object等,這些都是 Java 層面的類(lèi)型,而使用本地方法的處理過(guò)程需要有它們對(duì)應(yīng)的類(lèi)型。
大概的流程
Java 層編寫(xiě)的本地方法,被編譯器編譯為字節(jié)碼,字節(jié)碼將按照規(guī)范將不同類(lèi)型的參數(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);
上述對(duì)應(yīng)的方法被注冊(cè)JVM中,當(dāng)執(zhí)行到調(diào)用本地方法時(shí)則會(huì)按照類(lèi)型映射轉(zhuǎn)換成本地?cái)?shù)據(jù)類(lèi)型,比如int->jint和Object->jobject。這里其實(shí) int 和 jint 在 C++ 中是一樣的,只是用 typedef 定義了另外一個(gè)名稱(chēng)而已,而 jobject 是一個(gè)指針,執(zhí)行引擎在執(zhí)行 Java 層邏輯時(shí)生成了 Object 對(duì)象,它在 JVM 層有專(zhuān)門(mén)的數(shù)據(jù)結(jié)構(gòu),這里的 jobject 就是指向這個(gè)結(jié)構(gòu)的指針,在需要使用時(shí)可以強(qiáng)制轉(zhuǎn)換成 JVM 層的數(shù)據(jù)結(jié)構(gòu),然后即可對(duì)其進(jìn)行操作。另外,JVM 中用 oop 來(lái)表示對(duì)象指針。
基礎(chǔ)類(lèi)型映射
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位不帶符號(hào),Unicode字符 |
引用類(lèi)型映射
除了基礎(chǔ)的類(lèi)型映射外,Java 層其他對(duì)象類(lèi)型為引用類(lèi)型,那么本地方法對(duì)應(yīng)的是 jobject 類(lèi)型,另外,它還會(huì)派生出經(jīng)常用的一些子類(lèi),比如 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類(lèi),該類(lèi)為空類(lèi),而其他的類(lèi)包括_jclass _jthrowable _jstring _jarray都是繼承_jobject類(lèi)。此外,數(shù)組類(lèi)型還派生出了9個(gè)子類(lèi),分別對(duì)應(yīng)基礎(chǔ)類(lèi)型數(shù)組和引用類(lèi)型數(shù)組。
前面定義完類(lèi)后再定義指針別名,這里的就是本地方法的類(lèi)型了。另外,這些都是 C++ 的定義,如果是 C 編譯器則會(huì)使用 struct 來(lái)定義 _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的空類(lèi)
上面的引用類(lèi)型定義為空類(lèi),這里了解下C++的空類(lèi),通常我們要定義一個(gè)空類(lèi)可以如下兩種方式,
class Empty{} struct Empty{}
經(jīng)過(guò)上述定義后的空類(lèi),它的大小為1,但是一個(gè)空類(lèi)啥都沒(méi)有的話(huà)它有什么用呢?其實(shí)它可以用來(lái)區(qū)分不同的對(duì)象,空類(lèi)定義的不同對(duì)象擁有不同的地址,使用new操作出來(lái)的對(duì)象也有不同的指針,而且空類(lèi)也能區(qū)分不同的類(lèi)別。
指針轉(zhuǎn)換
所以有了這些類(lèi)型映射后我們是怎么聯(lián)系起來(lái)使用的呢?其實(shí)很簡(jiǎn)單,答案就是進(jìn)行指針轉(zhuǎn)換,前面提到過(guò) Java 層的對(duì)象在 JVM 中是有一定的數(shù)據(jù)結(jié)構(gòu)的,即用 oop 來(lái)表示對(duì)象指針,那么 jobject 可以作如下轉(zhuǎn)換,其中 handle 即為 jobject 類(lèi)型。
oop result = *reinterpret_cast<oop*>(handle);
轉(zhuǎn)換成 oop 后要進(jìn)一步處理就很方便了,比如想要獲取一些類(lèi)相關(guān)的元數(shù)據(jù)時(shí)可以使用其中的 klass 來(lái)獲取。
總結(jié)
以上,Java 層定義的類(lèi)型在本地方法有著與之相對(duì)應(yīng)的數(shù)據(jù)類(lèi)型,而且 Java 層源碼被編譯為字節(jié)碼后保存了本地方法參數(shù)對(duì)應(yīng)的類(lèi)型,JVM 執(zhí)行時(shí)可以根據(jù)不同的類(lèi)型轉(zhuǎn)換成本地方法對(duì)應(yīng)的類(lèi)型,而本地方法定義的類(lèi)型都為空類(lèi),主要作用是用來(lái)綁定對(duì)象,并且可以區(qū)分對(duì)象類(lèi)型,在必要時(shí)刻通過(guò)指針轉(zhuǎn)換即可訪(fǎng)問(wèn)對(duì)象或類(lèi)元數(shù)據(jù)。
- Java編碼輔助工具M(jìn)apstruct用法詳解
- MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法
- Java Map.get()返回指定鍵所映射的值
- Java HashSet(散列集),HashMap(散列映射)的簡(jiǎn)單介紹
- Java中具有映射關(guān)系的容器:數(shù)組和Map的區(qū)別說(shuō)明
- Java底層基于鏈表實(shí)現(xiàn)集合和映射--集合Set操作詳解
- Java實(shí)現(xiàn)鼠標(biāo)模擬與鍵盤(pán)映射
- javaMybatis映射屬性,高級(jí)映射詳解
- java 中MyBatis注解映射的實(shí)例詳解
- Java MapStruct解了對(duì)象映射的毒
相關(guān)文章
java如何根據(jù)IP獲取當(dāng)前區(qū)域天氣信息詳解
根據(jù)IP自動(dòng)獲取當(dāng)?shù)氐奶鞖忸A(yù)報(bào)信息這個(gè)功能大家應(yīng)該都遇到過(guò),天氣預(yù)報(bào)信息用途非常廣泛,篇文章主要給大家介紹了關(guān)于java如何根據(jù)IP獲取當(dāng)前區(qū)域天氣信息的相關(guān)資料,需要的朋友可以參考下2021-08-08解決idea check out 切換分支時(shí)找不到需要的分支問(wèn)題
這篇文章主要介紹了解決idea check out 切換分支時(shí)找不到需要的分支問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02Java實(shí)現(xiàn)簡(jiǎn)單GUI登錄和注冊(cè)界面
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單GUI登錄和注冊(cè)界面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04關(guān)于工廠(chǎng)方法模式的Java實(shí)現(xiàn)
這篇文章主要介紹了關(guān)于工廠(chǎng)方法模式的Java實(shí)現(xiàn)講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03JAVA項(xiàng)目如何打包部署到Linux服務(wù)器上
本文詳細(xì)介紹了在服務(wù)器上部署環(huán)境包括JDK、MySQL、Tomcat的設(shè)置,以及使用Idea-Maven-SpringBoot進(jìn)行jar包打包部署的流程,內(nèi)容涵蓋了MySQL配置注意事項(xiàng)、pom.xml配置、打包命令等關(guān)鍵步驟,同時(shí),也提供了如何將jar包上傳到Linux服務(wù)器并運(yùn)行的具體方法2024-10-10Java阻塞延遲隊(duì)列DelayQueue原理及使用詳解
這篇文章主要介紹了Java阻塞延遲隊(duì)列DelayQueue原理及使用詳解,阻塞隊(duì)列是一個(gè)支持兩個(gè)附加操作的隊(duì)列,這兩個(gè)附加的操作是:在隊(duì)列為空時(shí),從隊(duì)列中獲取元素的消費(fèi)者線(xiàn)程會(huì)一直等待直到隊(duì)列變?yōu)榉强?需要的朋友可以參考下2023-12-12詳解如何在springcloud分布式系統(tǒng)中實(shí)現(xiàn)分布式鎖
最近在看分布式鎖的資料,本文就介紹一下利用springcloud結(jié)合redis實(shí)現(xiàn)分布式鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Java實(shí)現(xiàn)用Freemarker完美導(dǎo)出word文檔(帶圖片)
這篇文章主要介紹了Java實(shí)現(xiàn)用Freemarker完美導(dǎo)出word文檔(帶圖片),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07Java阻塞隊(duì)列中的BlockingQueue接口詳解
這篇文章主要介紹了Java阻塞隊(duì)列中的BlockingQueue接口詳解,對(duì)于Queue而言,BlockingQueue是主要的線(xiàn)程安全的版本,具有阻塞功能,可以允許添加、刪除元素被阻塞,直到成功為止,BlockingQueue相對(duì)于Queue而言增加了兩個(gè)方法put、take元素,需要的朋友可以參考下2023-09-09