1. java对象的创建的步骤
- 函数NewObject可以创建java对象
- 用GetMethodID方法取得构造方法的jmethodID,传入方法名称设定为"<init>"表示取的是构造方法的methodID
- 构造方法的方法返回值类型的签名始终为Void
- 例子:
TestNative.java
package video1;
import java.util.Date;
public class TestNative {
public int number = 100;
public int signTest(int i, Date date, int[] arr) {
System.out.println("Sign Test");
return 0;
}
public TestNative() {
System.out.println("Default Constructor!");
}
public TestNative(int i, int j) {
this.number = i;
System.out.println("TestNative Constructor: i:" + i);
}
// native关键字修饰的方法,其内容是C/C++编写的,java中不必为它编写具体的实现
public native void sayHello();
public static void main(String[] args) {
System.loadLibrary("NativeCode");
TestNative tn = new TestNative();
tn.sayHello();
}
}
C/C++代码片段:
//找到class
jclass clazz_Kong=env->FindClass("video1/TestNative");
//获得构造函数ID
jmethodID MID_Kong=env->GetMethodID(clazz_Kong,"<init>","(II)V");
//生成对象 最后两个参数是构造函数的参数,可以不写
jobject obj_Kong = env->NewObject(clazz_Kong,MID_Kong,1999l,2l);
//调用属性
jfieldID Kong_num = env->GetFieldID(clazz_Kong,"number","I");
jint numberKong= env->GetIntField(obj_Kong,Kong_num);
cout<<"Kong:"<<numberKong<<endl;
- 另一种方法 AllocObject(不常用)
2. 在C/C++本地代码中访问JAVA的String字符串对象
- 在java中,使用的字符串String对象不论是中文还是英文符号,一个字符总是占两个字节
- java通过JNI接口可以将java的字符串转换到C/C++中的宽字符串(wchar_t*),或是传回一个UTF-8的字符串(char*)到C/C++.
- 反过来,C/C++可以通过一个宽字符串,或是一个UTF-8编码的字符串来创建一个java端的String对象
- 函数GetStringChars GetStringUTFChars
这两个函数用来取得某个jstring对象相关的Java字符串。
分别可以取得UTF-16编码的宽字符串(jchar*)跟UTF-8编码的字符串(char*)。
例如:
const jchar* GetStringChars(jstring str,jboolean* copied)
const char* GetStringUTFChars(jstirng str,jboolean* copied)
第一个参数传入一个指向java中的String对象的jstring变量,第二个参数传入一个jboolean的指针,是用来标识是否对java的String对象进行了拷贝。如果传入这个jboolean指针不是NULL,则它会给该指针所指向的内存传入JNI_TRUE或JNI_FALSE标识是否进行了拷贝。传入NULL表示不关心是否拷贝字符串,它就不会给jboolean*指向的内存赋值
这两个函数分别都会有两个不同的动作:
1.开新内存,然后把java中的string拷贝到这个内存中,然后返回指向这个内存地址的指针
2.直接返回指向java中String内存的指针,这个时候千万不要改变这个内存的内容,这将破坏String在java中始终是常量这个原则。
使用这两个函数取得的字符串,在不使用的时候,要使用ReleaseStringChars/ReleaseStringUTFChars来释放拷贝的内容,或是释放对java的String对象的引用
ReleaseStringChars(jstring jstr,const jchar * str);
ReleaseStringUTFChars(jstring jstr,const char * str);
第一个参数指定一个jstring变量,即是要释放的本地字符串的来源,第二个参数就是要释放的本地字符串
- 函数GetStringCritical
为了增加直接传回指向java字符串的指针的可能性(而不是拷贝),JDK1.2出来了新的函数
GetStringCritical/ReleaseStringCritical.
在GetStringCritical/ReleaseStringCritical之间是一个关键区,在关键区千万不要出现中断操作,或是在JVM中分配任何新对象,否则会造成JVM死锁
虽说这个函数会增加直接传回指向java字符串指针的可能性,不过还是会根据实际情况传回拷贝过的字符串
不支持GetStringUTFCritical
- 函数GetStringRegion/GetStringUTFRegion
动作:把java字符串的内容直接拷贝到C/C++的字符数组中。在呼叫这个函数之前必须有一个C/C++分配出来的字符串,然后传入到这个函数中进行字符串的拷贝(此函数不分配内存)
例子:
//拷贝Java字符串并以UTF-8编码传入buffer
GetStringUTFRegion(jstring str,jsize start,jsize len,char* buffer);
//拷贝java字符串并以UTF-16编码传入buffer
GetStringRegion(jstring str, jsize start,jsize len,jchar* buffer);
3. 在C/C++本地代码中创建JAVA的String字符串对象
- 函数
jstring NewString(const jchar* str,jsize len);
jstring NewStringUTF(const char * str);
//取得字符串的长度
jsize GetStringLength(jstring str);
jsize GetStringUTFLength(jstring str);
4. 字符串操作完整示例
TestNative1.java
package video1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class TestNative1 {
public String message = null;
public native void callCppFunction();
public static void main(String[] args) throws IOException {
System.loadLibrary("NativeCode");
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
String str = reader.readLine();
TestNative1 obj = new TestNative1();
obj.message = str;
obj.callCppFunction();
System.out.println("java output:" + obj.message);
}
}
cpp.cpp
#include "video1_TestNative1.h"
#include "windows.h"
#include <iostream>
using namespace std;
JNIEXPORT void JNICALL Java_video1_TestNative1_callCppFunction(JNIEnv * env, jobject obj){
jclass native_clazz = env->GetObjectClass(obj);
//得到jfieldID
jfieldID fieldID_msg = env->GetFieldID(native_clazz,"message","Ljava/lang/String;");
//得到java字符串
jstring j_msg =(jstring) env->GetObjectField(obj,fieldID_msg);
//将java字符串转换为本地字符串
const jchar * jstr = env->GetStringChars(j_msg,NULL);
MessageBoxW(NULL,(const wchar_t*)jstr,L"Title",MB_OK);//对话框弹出
env->ReleaseStringChars(j_msg,jstr);//释放资源
//修改字符串
}