JNI 常用API
2015-09-17 14:10
267 查看
利用JNIEnv自变量,程序员可访问一系列函数。这些函数可划分为下述类别:
■获取版本信息
■进行类和对象操作
■控制对Java对象的全局和局部引用
■访问实例字段和静态字段
■调用实例方法和静态方法
■执行字串和数组操作
■产生和控制Java异常
获取版本信息
获取JNI函数版本信息,
返回值为
InJDK/JRE1.1,
InJDK/JRE1.2,
InJDK/JRE1.4,
在
参数:
SINCEJDK/JRE1.2:
产生和控制Java异常
通过消息构造一个异常类,其中参数
测试JVM是否有异常发生
SINCEJDK/JRE1.2:
localreference和globalreference。
Java和JNI代码之间函数调用时,简单类型,也就是内置类型,比如int,char等是值传递(passbyvalue),而其它Java对象都是引用传递(passbyreference),这些对象引用由JVM传给JNI代码,每个都有其生命周期。
JNI函数参数中jobject或者它的子类,其参数都是localreference。Localreference只在这个JNI函数中有效,JNI函数返回后,引用的对象就被释放,它的生命周期就结束了。若要留着日后使用,则需根据这个localreference创建globalreference。Globalreference不会被系统自动释放,它仅当被程序明确调用DeleteGlobalReference时才被回收。(JNI多线程机制)
创建一个新的全局的引用,只能使用
参数:
JDK/JRE1.1提供了上面的DeleteLocalRef函数,使程序员可以手动删除本地引用。例如,如果本机代码遍历可能很大的对象或数组,并使用每个迭代中的一个元素,好的做法是下一次迭代中创建一个新的本地引用之前删除本地元素的引用。
JDK/JRE1.2和更高版本为本地引用生存周期管理提供了一套额外的函数。他们是下面列出的四种函数。
通知JVM您将使用超过16个本地引用。这将允许JVM优化对该本机代码的本地引用的处理
先调用PushLocalFrame,然后创建局部引用,并对其进行处理,最后调用PushLocalFrame释放局部引用,这时Java虚拟机也可以对其指向的对象进行垃圾回收。可以用C语言的栈来理解这对JNIAPI,调用PushLocalFrame之后Native代码创建的所有局部引用全部入栈,当调用PopLocalFrame之后,入栈的局部引用除了需要返回的局部引用(PushLocalFrame和PopLocalFrame这对函数可以返回一个局部引用给外部)之外,全部出栈,Java虚拟机这时可以释放他们指向的对象。具体的用法可以参考手册。这两个函数使JNI的局部引用由于和C语言的局部变量用法类似,所以强烈推荐使用
1、Java虚拟机默认为Native引用分配的局部引用数量是有限的,大部分的Java虚拟机实现默认分配16个局部引用。当然Java虚拟机也提供API(PushLocalFrame,EnsureLocalCapacity)让你申请更多的局部引用数量(Java虚拟机不保证你一定能申请到)。有限的资源当然要省着点用,否则将会被Java虚拟机无情抛弃(程序崩溃)。JNI编程中,实现Native代码时强烈建议调用PushLocalFrame,EnsureLocalCapacity来确保Java虚拟机为你准备好了局部变量空间。
2、如果你实现的Native函数是工具函数,会被频繁的调用。如果你在Native函数中没有显示删除局部引用,那么每次调用该函数Java虚拟机都会创建一个新的局部引用,造成局部引用过多。尤其是该函数在Native代码中被频繁调用,代码的控制权没有交还给Java虚拟机,所以Java虚拟机根本没有机会释放这些局部变量。退一步讲,就算该函数直接返回给Java虚拟机,也不能保证没有问题,我们不能假设Native函数返回Java虚拟机之后,Java虚拟机马上就会回收Native函数中创建的局部引用,依赖于Java虚拟机实现。所以我们在实现Native函数时一定要记着删除不
必要的局部引用,否则你的程序就有潜在的风险,不知道什么时候就会爆发。
3、如果你Native函数根本就不返回。比如消息循环函数——死循环等待消息,处理消息。如果你不显示删除局部引用,很快将会造成Java虚拟机的局部引用内存溢出。
WeakGlobalReferences
全局的弱引用是一种特殊的全局引用,与普通的全局引用不同全局的弱引用允许Java对象进行垃圾回收,当垃圾收集器运行时,它将释放对象,如果引用的对象只使用弱引用
SINCEJDK/JRE1.2:
ObjectOperations
分配一个新的Java对象,而不调用任何对象的构造函数,仅仅是内存创建
分配一个新的java对象,调用指定的构造函数,构造函数使用
根据类的引用返回类的类型
AccessingFieldsofObjects
参数:
Get<type>FieldRoutines
NativeTypeGet<type>Field
获取java对象属性的值
Set<type>FieldRoutines
NativeType
表3-4Set<type>FieldFamilyofAccessorRoutines
设置java对象属性的值
GetMethodID得到java类中方法的ID,它只能调用类中声明为public的方法,
参数:
NativeTypeCall<type>Method
NativeTypeCall<type>MethodA
NativeTypeCall<type>MethodV
调用java方法通过
如果想要调用一个对象的父类方法,而不是子类的这个方法的话,就可以使用NativeTypeCallNonvirtual<type>Method
NativeTypeCallNonvirtual<type>MethodA
NativeTypeCallNonvirtual<type>MethodV
例:
packagecom.cn;
publicclassFather{
publicvoidfunction(){
System.out.println("Father:function");
}
}
1.packagecom.cn;
2.publicclassChildextendsFather{
3.publicvoidfunction(){
4.System.out.println("Child:function");
5.}
6.}
packagecom.cn;
publicclassTestNativeCall{
publicnativevoidtestCall();
publicFatherp=newChild();
publicstaticvoidmain(String[]args){
System.loadLibrary("nativeCode");//Java类中加载DLL,然后调用声明的native方法
TestNativeCalltst=newTestNativeCall();
tst.testCall();
}
}
voidJava_Com_Cn_testCall(JNIEnv*env,jobjectobj){
jfieldIDid_p=env->GetFieldID(clazz_TestNative,"p","Lcom/cn/Father;");
jobjectp=env->GetObjectField(obj,id_p);//取得属性
jclassclazz_Father=env->FindClass("com/cn/Father");//找到Father类
jmethodIDid_Father_function=env->GetMethodID(clazz_Father,"function","()V");//获取Father类里面方法的ID
//调用方法,取得的是子类方法
env->CallVoidMethod(p,id_Father_function);
//调用父类方法
env->CallNonvirtualVoidMethod(p,clazz_Father,id_Father_function);
}
参数:
GetStatic<type>FieldRoutines
NativeTypeGetStatic<type>Field
获取java对象静态属性的值
SetStatic<type>FieldRoutines
设置java对象静态属性的值
NativeTypeCallStatic<type>Method
NativeTypeCallStatic<type>MethodA
NativeTypeCallStatic<type>MethodV
ArrayOperations
RegisteringNativeMethods
typedefstruct{
char*name;
char*signature;
void*fnPtr;
}JNINativeMethod
MonitorOperations
NIOSupport
TheNIO-relatedentrypointsallownativecodetoaccess
pleaseseeNewI/OAPIsandthespecificationofthejava.nio.ByteBufferclass.
ThreenewfunctionsintroducedinJDK/JRE1.4allowJNIcodetocreate,examine,andmanipulatedirectbuffers:
ReflectionSupport
■获取版本信息
■进行类和对象操作
■控制对Java对象的全局和局部引用
■访问实例字段和静态字段
■调用实例方法和静态方法
■执行字串和数组操作
■产生和控制Java异常
获取版本信息
jintGetVersion(JNIEnv*env);
获取JNI函数版本信息,
返回值为
jint
类型,在c/c++中jint为32位数,其中高16位是主版本号,低16位是从版本号
InJDK/JRE1.1,
GetVersion()returns
0x00010001.
InJDK/JRE1.2,
GetVersion()returns
0x00010002.
InJDK/JRE1.4,
GetVersion()returns
0x00010004.
jclassFindClass(JNIEnv*env,constchar*name);
在
CLASSPATH
环境变量中搜索目录和zip文件中具有指定名称的类。
参数:
name:afully-qualifiedclassname完全限定类,给出完整的类路径,包名和类名使用“
/”隔开
SINCEJDK/JRE1.2:
产生和控制Java异常
jintThrow(JNIEnv*env,jthrowableobj);
抛出异常
参数:
jthrowable是
java.lang.Throwable包中对象.
jintThrowNew(JNIEnv*env,jclassclazz,
constchar*message);
通过消息构造一个异常类,其中参数
clazz为
java.lang.Throwable包中的子类
jthrowableExceptionOccurred(JNIEnv*env);
测试JVM是否有异常发生
SINCEJDK/JRE1.2:
localreference和globalreference。
Java和JNI代码之间函数调用时,简单类型,也就是内置类型,比如int,char等是值传递(passbyvalue),而其它Java对象都是引用传递(passbyreference),这些对象引用由JVM传给JNI代码,每个都有其生命周期。
JNI函数参数中jobject或者它的子类,其参数都是localreference。Localreference只在这个JNI函数中有效,JNI函数返回后,引用的对象就被释放,它的生命周期就结束了。若要留着日后使用,则需根据这个localreference创建globalreference。Globalreference不会被系统自动释放,它仅当被程序明确调用DeleteGlobalReference时才被回收。(JNI多线程机制)
jobjectNewGlobalRef(JNIEnv*env,jobjectobj);
创建一个新的全局的引用,只能使用
DeleteGlobalRef
()函数销毁这个全局引用
参数:
Obj
一个本地引用或者全局引用
voidDeleteGlobalRef(JNIEnv*env,jobjectglobalRef);
销毁全局引用
参数:
globalRef
使用
NewGlobalRef
()函数生成的全局引用
voidDeleteLocalRef(JNIEnv*env,jobjectlocalRef);
销毁本地的引用
注意:
JDK/JRE1.1提供了上面的DeleteLocalRef函数,使程序员可以手动删除本地引用。例如,如果本机代码遍历可能很大的对象或数组,并使用每个迭代中的一个元素,好的做法是下一次迭代中创建一个新的本地引用之前删除本地元素的引用。
JDK/JRE1.2和更高版本为本地引用生存周期管理提供了一套额外的函数。他们是下面列出的四种函数。
jintEnsureLocalCapacity(JNIEnv*env,jintcapacity);
通知JVM您将使用超过16个本地引用。这将允许JVM优化对该本机代码的本地引用的处理
jintPushLocalFrame(JNIEnv*env,jintcapacity);
jobjectPopLocalFrame(JNIEnv*env,jobjectresult);
先调用PushLocalFrame,然后创建局部引用,并对其进行处理,最后调用PushLocalFrame释放局部引用,这时Java虚拟机也可以对其指向的对象进行垃圾回收。可以用C语言的栈来理解这对JNIAPI,调用PushLocalFrame之后Native代码创建的所有局部引用全部入栈,当调用PopLocalFrame之后,入栈的局部引用除了需要返回的局部引用(PushLocalFrame和PopLocalFrame这对函数可以返回一个局部引用给外部)之外,全部出栈,Java虚拟机这时可以释放他们指向的对象。具体的用法可以参考手册。这两个函数使JNI的局部引用由于和C语言的局部变量用法类似,所以强烈推荐使用
jobjectNewLocalRef(JNIEnv*env,jobjectref);
1、Java虚拟机默认为Native引用分配的局部引用数量是有限的,大部分的Java虚拟机实现默认分配16个局部引用。当然Java虚拟机也提供API(PushLocalFrame,EnsureLocalCapacity)让你申请更多的局部引用数量(Java虚拟机不保证你一定能申请到)。有限的资源当然要省着点用,否则将会被Java虚拟机无情抛弃(程序崩溃)。JNI编程中,实现Native代码时强烈建议调用PushLocalFrame,EnsureLocalCapacity来确保Java虚拟机为你准备好了局部变量空间。
2、如果你实现的Native函数是工具函数,会被频繁的调用。如果你在Native函数中没有显示删除局部引用,那么每次调用该函数Java虚拟机都会创建一个新的局部引用,造成局部引用过多。尤其是该函数在Native代码中被频繁调用,代码的控制权没有交还给Java虚拟机,所以Java虚拟机根本没有机会释放这些局部变量。退一步讲,就算该函数直接返回给Java虚拟机,也不能保证没有问题,我们不能假设Native函数返回Java虚拟机之后,Java虚拟机马上就会回收Native函数中创建的局部引用,依赖于Java虚拟机实现。所以我们在实现Native函数时一定要记着删除不
必要的局部引用,否则你的程序就有潜在的风险,不知道什么时候就会爆发。
3、如果你Native函数根本就不返回。比如消息循环函数——死循环等待消息,处理消息。如果你不显示删除局部引用,很快将会造成Java虚拟机的局部引用内存溢出。
WeakGlobalReferences
全局的弱引用是一种特殊的全局引用,与普通的全局引用不同全局的弱引用允许Java对象进行垃圾回收,当垃圾收集器运行时,它将释放对象,如果引用的对象只使用弱引用
jweakNewWeakGlobalRef(JNIEnv*env,jobjectobj);
voidDeleteWeakGlobalRef(JNIEnv*env,jweakobj);
SINCEJDK/JRE1.2:
ObjectOperations
jobjectAllocObject(JNIEnv*env,jclassclazz);
分配一个新的Java对象,而不调用任何对象的构造函数,仅仅是内存创建
jobjectNewObject(JNIEnv*env,jclassclazz,
jmethodIDmethodID,...);
jobjectNewObjectA(JNIEnv*env,jclassclazz,
jmethodIDmethodID,jvalue*args);
args:anarrayofargumentstotheconstructor.
jobjectNewObjectV(JNIEnv*env,jclassclazz,
jmethodIDmethodID,va_listargs);
args:ava_listofargumentstotheconstructor.
分配一个新的java对象,调用指定的构造函数,构造函数使用
methodID
指定
jclassGetObjectClass(JNIEnv*env,jobjectobj);
根据类的引用返回类的类型
jbooleanIsInstanceOf(JNIEnv*env,jobjectobj,
jclassclazz);
测试类的引用类型,是返回
JNI_TRUE否则返回
JNI_FALSE
jbooleanIsSameObject(JNIEnv*env,jobjectref1,
jobjectref2);
测试两个引用类型是否指向同一个空间,是返回
JNI_TRUE否则返回
JNI_FALSE
AccessingFieldsofObjects
jfieldIDGetFieldID(JNIEnv*env,jclassclazz,
constchar*name,constchar*sig);
GetFieldID
是得到
java
类中的参数
ID
,只能调用类中声明为
public
的属性,
jfieldID
为Get<type>FieldandSet<type>Field函数族使用
参数:
Name
属性在
java
类中的名字
Sig类型签名
Get<type>FieldRoutines
NativeTypeGet<type>Field
(JNIEnv*env,jobjectobj,
jfieldIDfieldID);
表3-3Get<type>FieldFamilyofAccessorRoutines |
Get<type>FieldRoutineName | NativeType |
GetObjectField() | jobject |
GetBooleanField() | jboolean |
GetByteField() | jbyte |
GetCharField() | jchar |
GetShortField() | jshort |
GetIntField() | jint |
GetLongField() | jlong |
GetFloatField() | jfloat |
GetDoubleField() | jdouble |
Set<type>FieldRoutines
voidSet<type>Field
(JNIEnv*env,jobjectobj,jfieldIDfieldID,
NativeType
value);
表3-4Set<type>FieldFamilyofAccessorRoutines
Set<type>FieldRoutineName | NativeType |
SetObjectField() | jobject |
SetBooleanField() | jboolean |
SetByteField() | jbyte |
SetCharField() | jchar |
SetShortField() | jshort |
SetIntField() | jint |
SetLongField() | jlong |
SetFloatField() | jfloat |
SetDoubleField() | jdouble |
CallingInstanceMethods
jmethodIDGetMethodID(JNIEnv*env,jclassclazz,
constchar*name,constchar*sig);
GetMethodID得到java类中方法的ID,它只能调用类中声明为public的方法,
jmethodID
为Call<type>Method函数族使用
参数:
Name
方法在
java
类中的名字
Sig类型签名
NativeTypeCall<type>Method
(JNIEnv*env,jobjectobj,
jmethodIDmethodID,...);
NativeTypeCall<type>MethodA
(JNIEnv*env,jobjectobj,
jmethodIDmethodID,jvalue*args);
NativeTypeCall<type>MethodV
(JNIEnv*env,jobjectobj,
jmethodIDmethodID,va_listargs);
表3-5InstanceMethodCallingRoutines |
Call<type>MethodRoutineName | NativeType |
CallVoidMethod() CallVoidMethodA() CallVoidMethodV() | void |
CallObjectMethod() CallObjectMethodA() CallObjectMethodV() | jobject |
CallBooleanMethod() CallBooleanMethodA() CallBooleanMethodV() | jboolean |
CallByteMethod() CallByteMethodA() CallByteMethodV() | jbyte |
CallCharMethod() CallCharMethodA() CallCharMethodV() | jchar |
CallShortMethod() CallShortMethodA() CallShortMethodV() | jshort |
CallIntMethod() CallIntMethodA() CallIntMethodV() | jint |
CallLongMethod() CallLongMethodA() CallLongMethodV() | jlong |
CallFloatMethod() CallFloatMethodA() CallFloatMethodV() | jfloat |
CallDoubleMethod() CallDoubleMethodA() CallDoubleMethodV() | jdouble |
jmethodID
指定
如果想要调用一个对象的父类方法,而不是子类的这个方法的话,就可以使用NativeTypeCallNonvirtual<type>Method
(JNIEnv*env,jobjectobj,
jclassclazz,jmethodIDmethodID,...);
NativeTypeCallNonvirtual<type>MethodA
(JNIEnv*env,jobjectobj,
jclassclazz,jmethodIDmethodID,jvalue*args);
NativeTypeCallNonvirtual<type>MethodV
(JNIEnv*env,jobjectobj,
jclassclazz,jmethodIDmethodID,va_listargs);
表3-6CallNonvirtual<type>MethodRoutines |
CallNonvirtual<type>MethodRoutineName | NativeType |
CallNonvirtualVoidMethod() CallNonvirtualVoidMethodA() CallNonvirtualVoidMethodV() | void |
CallNonvirtualObjectMethod() CallNonvirtualObjectMethodA() CallNonvirtualObjectMethodV() | jobject |
CallNonvirtualBooleanMethod() CallNonvirtualBooleanMethodA() CallNonvirtualBooleanMethodV() | jboolean |
CallNonvirtualByteMethod() CallNonvirtualByteMethodA() CallNonvirtualByteMethodV() | jbyte |
CallNonvirtualCharMethod() CallNonvirtualCharMethodA() CallNonvirtualCharMethodV() | jchar |
CallNonvirtualShortMethod() CallNonvirtualShortMethodA() CallNonvirtualShortMethodV() | jshort |
CallNonvirtualIntMethod() CallNonvirtualIntMethodA() CallNonvirtualIntMethodV() | jint |
CallNonvirtualLongMethod() CallNonvirtualLongMethodA() CallNonvirtualLongMethodV() | jlong |
CallNonvirtualFloatMethod() CallNonvirtualFloatMethodA() CallNonvirtualFloatMethodV() | jfloat |
CallNonvirtualDoubleMethod() CallNonvirtualDoubleMethodA() CallNonvirtualDoubleMethodV() | jdouble |
packagecom.cn;
publicclassFather{
publicvoidfunction(){
System.out.println("Father:function");
}
}
1.packagecom.cn;
2.publicclassChildextendsFather{
3.publicvoidfunction(){
4.System.out.println("Child:function");
5.}
6.}
packagecom.cn;
publicclassTestNativeCall{
publicnativevoidtestCall();
publicFatherp=newChild();
publicstaticvoidmain(String[]args){
System.loadLibrary("nativeCode");//Java类中加载DLL,然后调用声明的native方法
TestNativeCalltst=newTestNativeCall();
tst.testCall();
}
}
voidJava_Com_Cn_testCall(JNIEnv*env,jobjectobj){
jfieldIDid_p=env->GetFieldID(clazz_TestNative,"p","Lcom/cn/Father;");
jobjectp=env->GetObjectField(obj,id_p);//取得属性
jclassclazz_Father=env->FindClass("com/cn/Father");//找到Father类
jmethodIDid_Father_function=env->GetMethodID(clazz_Father,"function","()V");//获取Father类里面方法的ID
//调用方法,取得的是子类方法
env->CallVoidMethod(p,id_Father_function);
//调用父类方法
env->CallNonvirtualVoidMethod(p,clazz_Father,id_Father_function);
}
AccessingStaticFields
jfieldIDGetStaticFieldID(JNIEnv*env,jclassclazz,
constchar*name,constchar*sig);
GetStaticFieldID得到java类中static属性ID,
jfieldID
为GetStatic<type>FieldandSetStatic<type>Field函数族使用
参数:
clazzjava
类对象
name
方法在
java
类中的名字
sig类型签名
GetStatic<type>FieldRoutines
NativeTypeGetStatic<type>Field
(JNIEnv*env,jclassclazz,
jfieldIDfieldID);
表3-7 | GetStatic<type>FieldFamilyofAccessorRoutines |
GetStatic<type>FieldRoutineName | NativeType |
GetStaticObjectField() | jobject |
GetStaticBooleanField() | jboolean |
GetStaticByteField() | jbyte |
GetStaticCharField() | jchar |
GetStaticShortField() | jshort |
GetStaticIntField() | jint |
GetStaticLongField() | jlong |
GetStaticFloatField() | jfloat |
GetStaticDoubleField() | jdouble |
获取java对象静态属性的值
SetStatic<type>FieldRoutines
voidSetStatic<type>Field
(JNIEnv*env,jclassclazz,
jfieldIDfieldID,NativeType
value);
表3-8 | SetStatic<type>FieldFamilyofAccessorRoutines |
SetStatic<type>FieldRoutineName | NativeType |
SetStaticObjectField() | jobject |
SetStaticBooleanField() | jboolean |
SetStaticByteField() | jbyte |
SetStaticCharField() | jchar |
SetStaticShortField() | jshort |
SetStaticIntField() | jint |
SetStaticLongField() | jlong |
SetStaticFloatField() | jfloat |
SetStaticDoubleField() | jdouble |
CallingStaticMethods
GetStaticMethodID
jmethodIDGetStaticMethodID(JNIEnv*env,jclassclazz,
constchar*name,constchar*sig);
GetStaticMethodID得到java类中static方法ID,
jmethodID
为CallStatic<type>Method函数使用
NativeTypeCallStatic<type>Method
(JNIEnv*env,jclassclazz,
jmethodIDmethodID,...);
NativeTypeCallStatic<type>MethodA
(JNIEnv*env,jclassclazz,
jmethodIDmethodID,jvalue*args);
NativeTypeCallStatic<type>MethodV
(JNIEnv*env,jclassclazz,
jmethodIDmethodID,va_listargs);
表3-9CallStatic<type>MethodCallingRoutines |
CallStatic<type>MethodRoutineName | NativeType |
CallStaticVoidMethod() CallStaticVoidMethodA() CallStaticVoidMethodV() | void |
CallStaticObjectMethod() CallStaticObjectMethodA() CallStaticObjectMethodV() | jobject |
CallStaticBooleanMethod() CallStaticBooleanMethodA() CallStaticBooleanMethodV() | jboolean |
CallStaticByteMethod() CallStaticByteMethodA() CallStaticByteMethodV() | jbyte |
CallStaticCharMethod() CallStaticCharMethodA() CallStaticCharMethodV() | jchar |
CallStaticShortMethod() CallStaticShortMethodA() CallStaticShortMethodV() | jshort |
CallStaticIntMethod() CallStaticIntMethodA() CallStaticIntMethodV() | jint |
CallStaticLongMethod() CallStaticLongMethodA() CallStaticLongMethodV() | jlong |
CallStaticFloatMethod() CallStaticFloatMethodA() CallStaticFloatMethodV() | jfloat |
CallStaticDoubleMethod() CallStaticDoubleMethodA() CallStaticDoubleMethodV() | jdouble |
StringOperations
jstringNewString(JNIEnv*env,constjchar*unicodeChars,
jsizelen);
ArrayOperations
RegisteringNativeMethods
jintRegisterNatives(JNIEnv*env,jclassclazz,
constJNINativeMethod*methods,jintnMethods);
typedefstruct{
char*name;
char*signature;
void*fnPtr;
}JNINativeMethod
MonitorOperations
jintMonitorEnter(JNIEnv*env,jobjectobj);
jintMonitorExit(JNIEnv*env,jobjectobj);
NIOSupport
TheNIO-relatedentrypointsallownativecodetoaccess
java.niodirectbuffers.Thecontentsofadirectbuffercan,potentially,resideinnativememoryoutsideoftheordinarygarbage-collectedheap.Forinformationaboutdirectbuffers,
pleasesee
ThreenewfunctionsintroducedinJDK/JRE1.4allowJNIcodetocreate,examine,andmanipulatedirectbuffers:
NewDirectByteBuffer
GetDirectBufferAddress
GetDirectBufferCapacity
ReflectionSupport
JavaVMInterface
jintGetJavaVM(JNIEnv*env,JavaVM**vm);
相关文章推荐
- 关于引用及取地址&运算符的用法
- HDU 4291 A Short problem
- 我的Android进阶之旅------>Android使用百度地图时,关于android.permission.BAIDU_LOCATION_SERVICE的声明警告。
- Spring AOP + AspectJ annotation example
- VB截取中英文混合字符串中若干半角单位长字串的函数
- json格式化工具
- QT中监控全局键盘鼠标事件
- Java中的StringUtils类
- 浅谈数据结构-插入排序(直接插入、希尔排序)
- 如何检测 JavaScript 中的自定义全局变量
- 有效减少虚拟机镜像文件的大小
- Win10提示“计算机内存不足”的怎么办 解决办法介绍
- test3.10
- 11.2.04 Oracle RAC 目录中 crfclust.bdb文件过大,Bug 20186278
- android代码获取网站图标
- 移除父控件的所有子控件
- activiti数据库表结构剖析
- Android 三次贝塞尔曲线练习之弹性的圆
- 支付宝添加scheme的方法
- 如何解析Plist文件?