Types JNI.h j类型和关系
我在这里看到了Types JNI.h j类型和关系,types,jvm,java-native-interface,Types,Jvm,Java Native Interface,我在这里看到了jni.h的代码: http://xdprof.sourceforge.net/doxygen/jni_8h-source.html 我想知道这是什么: class _jobject {}; 00053 class _jclass : public _jobject {}; 00054 class _jthrowable : public _jobject {}; 00055 class _jstring : public _jobject {}; 00056 class _jar
jni.h
的代码:
http://xdprof.sourceforge.net/doxygen/jni_8h-source.html
我想知道这是什么:
class _jobject {};
00053 class _jclass : public _jobject {};
00054 class _jthrowable : public _jobject {};
00055 class _jstring : public _jobject {};
00056 class _jarray : public _jobject {};
00057 class _jbooleanArray : public _jarray {};
00058 class _jbyteArray : public _jarray {};
00059 class _jcharArray : public _jarray {};
00060 class _jshortArray : public _jarray {};
00061 class _jintArray : public _jarray {};
00062 class _jlongArray : public _jarray {};
00063 class _jfloatArray : public _jarray {};
00064 class _jdoubleArray : public _jarray {};
00065 class _jobjectArray : public _jarray {};
例如,
\u jobject
空类和对象
类-“Object.h/Object.cpp
”(在JVM内部)之间的关系是什么?为什么这些类是空的?这可能在不同的运行时实现中有所不同,但我将以Android的旧Dalvik运行时为例
定义为\u jobject*
的jobject
是间接引用。指针的位不是用作普通指针,而是用于编码引用类型(本地、全局、弱全局)和引用表索引()
因此,当您将
jobject
传递给某个JNI函数(例如NewGlobalRef
)时,jobject
将被传递给,它确定引用类型,并从相应的引用表中返回相应的对象*
。这可能在不同的运行时实现中有所不同,但我将以Android的旧Dalvik运行时为例
定义为\u jobject*
的jobject
是间接引用。指针的位不是用作普通指针,而是用于编码引用类型(本地、全局、弱全局)和引用表索引()
因此,当您将
jobject
传递给某个JNI函数(例如NewGlobalRef
)时,jobject
将被传递给,这决定了引用类型,并从相应的引用表中返回相应的对象*
。这些类仅用于维护相应JNI类型之间的层次结构:
jobject <- jarray <- jintArray etc.
此类操作的类型安全性可能在运行时强制执行,也可能不强制执行,具体取决于JVM实现。例如,如果您传递一些精心编制的jstring
参数,而该参数实际上不是java.lang.String
对象的句柄,则HotSpot可能会崩溃
编辑
jstring
是指向Java字符串实例的指针(注意双间接寻址)。JVM不访问class\u jstring
的值,而是将其视为指向实际实例的指针(参见上面的示例)
然后,为了读取oop的字段,JVM使用原始指针算法(假设它知道字段值
与java.lang.String实例开头的偏移量为12):
其他JVM实现可能会以不同的方式对待
class\u jstring
。其思想是使JNI类型不透明,以便不同的JVM可以以自己的方式实现JNI句柄,而无需重新编译使用这些句柄的代码。这就是为什么类的内容无关紧要的原因-这只是声明,而不是类型的实际定义。这些类仅用于维护相应JNI类型之间的层次结构:
jobject <- jarray <- jintArray etc.
此类操作的类型安全性可能在运行时强制执行,也可能不强制执行,具体取决于JVM实现。例如,如果您传递一些精心编制的jstring
参数,而该参数实际上不是java.lang.String
对象的句柄,则HotSpot可能会崩溃
编辑
jstring
是指向Java字符串实例的指针(注意双间接寻址)。JVM不访问class\u jstring
的值,而是将其视为指向实际实例的指针(参见上面的示例)
然后,为了读取oop的字段,JVM使用原始指针算法(假设它知道字段值
与java.lang.String实例开头的偏移量为12):
其他JVM实现可能会以不同的方式对待
class\u jstring
。其思想是使JNI类型不透明,以便不同的JVM可以以自己的方式实现JNI句柄,而无需重新编译使用这些句柄的代码。这就是为什么类的内容不重要——这只是声明,而不是类型的实际定义。JNI不是C++接口,它是纯C接口。幸运的是,JNI有一个C++包装器,在C++编译器可以帮助的时候减少样板代码,并且避免(一些)错误,其中C++类型的系统可以减少歧义。
在你发布的C++引擎下,所有JNI对象使用由JNI函数解释的黑盒句柄(可以称之为对象引用)。在Dalvik JVM上,其中一些句柄只是指向JVM内部表的指针,但这是一个实现细节,可能只与某些调试相关
这种实现细节在切换到其他JVM时,包括现代Android艺术造成了很大的麻烦,因为使用指针,有时我们可以避开与本地引用混合的全局引用等。
JNI不是C++接口,它是纯C接口。幸运的是,JNI有一个C++包装器,在C++编译器可以帮助的时候减少样板代码,并且避免(一些)错误,其中C++类型的系统可以减少歧义。
在你发布的C++引擎下,所有JNI对象使用由JNI函数解释的黑盒句柄(可以称之为对象引用)。在Dalvik JVM上,其中一些句柄只是指向JVM内部表的指针,但这是一个实现细节,可能只与某些调试相关
这个实现细节在切换到其他JVM(包括现代Android ART)时造成了很大的麻烦,因为使用指针,我们有时可以避开全局引用和局部引用的混合,等等。变量字符串的值是多少?类jstring为空,因此,变量是一个带有空字段的jstring对象。那么JVM如何知道变量字符串字符串值包含什么呢?我认为这段代码并没有显式地强制转换JNI句柄。首先,它抽取了一名实习生
java.lang.String JNIHandleBlock jstring string
------------------ ----------------------- -----------------
| 0: (header) |<---\ | oop[0] | /---| class _jclass * |
| 8: (class ptr) | \---| oop[1] <------------------/ -----------------
| 12: char[] value | | ... |
| 16: int hash | | oop[31] |
| 24: (padding) | | |
------------------ | int _top |
| JNIHandleBlock* _next |
| ... |
-----------------------
oop s = JNIHandles::resolve_non_null(string);
// This is effectively the same as
// oop s = *(oop*)string;
java_lang_String::value(s)
// Effectively the same as
// s->obj_field(12)
// which is expanded to something like
// *(oop*)((intptr_t)s + 12)