JNI之String类型

JNI使用的是改良的UTF-8格式的Strings。java

如下文档来自官方:程序员

Modified UTF-8 Strings

The JNI uses modified UTF-8 strings to represent various string types. Modified UTF-8 strings are the same as those used by the Java VM. Modified UTF-8 strings are encoded so that character sequences that contain only non-null ASCII characters can be represented using only one byte per character, but all Unicode characters can be represented.数组

翻译:安全

JNI使用的是改良的UTF-8格式的Strings来表示各类字符串类型。改良的UTF-8的strings和Java VM使用的是同样的。改良的UTF-8的strings编码,使得仅包含非空ASCII字符的字符序列可以按每字符占一个字节表示,但全部的Unicode字符都可以被表示出来。ide

String Operations(String 操做)

1.NewString -- 建立String

jstring NewString(JNIEnv *env, const jchar *unicodeChars,jsize len);

Constructs a new java.lang.String object from an array of Unicode characters.函数

经过Unicode字符的数组来建立一个新的String对象。备注:Unicode和UTF-8仍是有区别的。编码

参数spa

env:JNI 接口指针。.net

unicodeChars:指向 Unicode 字符串的指针。线程

len:Unicode 字符串的长度。

返回值

Java 字符串对象。若是没法构造该字符串,则为 NULL

抛出

OutOfMemoryError:若是系统内存不足。

 

2.GetStringLength -- 获取String的长度

jsize GetStringLength(JNIEnv *env, jstring string);

Returns the length (the count of Unicode characters) of a Java string.

返回 Java 字符串的长度(Unicode 字符数)。

参数:

env:JNI 接口指针。

string:Java 字符串对象。

返回值:

Java 字符串的长度。

 

3.GetStringChars  -- 获取StringChars的指针

const jchar * GetStringChars(JNIEnv *env, jstring string,jboolean *isCopy);

Returns a pointer to the array of Unicode characters of the string. This pointer is valid until ReleaseStringchars() is called.

If isCopy is not NULL, then *isCopy is set to JNI_TRUE if a copy is made; or it is set to JNI_FALSE if no copy is made.

返回指向字符串的 Unicode 字符数组的指针。该指针在调用 ReleaseStringchars() 前一直有效。

若是 isCopy 非空,则在复制完成后将 *isCopy 设为 JNI_TRUE。若是没有复制,则设为JNI_FALSE

参数:

env:JNI 接口指针。

string:Java 字符串对象。

isCopy:指向布尔值的指针。

返回值:

指向 Unicode 字符串的指针,若是操做失败,则返回NULL

 

4.ReleaseStringChars -- 释放StringChars

void ReleaseStringChars(JNIEnv *env, jstring string,const jchar *chars);

Informs the VM that the native code no longer needs access to chars. The chars argument is a pointer obtained from string using GetStringChars().

通知虚拟机平台相关代码无需再访问 chars。参数 chars 是一个指针,可经过 GetStringChars() 从 string 得到。

参数:

env:JNI 接口指针。

string:Java 字符串对象。

chars:指向 Unicode 字符串的指针。

 

UTF-8

5.NewStringUTF -- 建立UTF的String

jstring NewStringUTF(JNIEnv *env, const char *bytes);

Constructs a new java.lang.String object from an array of characters in modified UTF-8 encoding.

经过改良的 UTF-8 字符数组构造新 java.lang.String 对象。

参数:

env:JNI 接口指针。若是没法构造该字符串,则为 NULL

bytes:指向 UTF-8 字符串的指针。

返回值:

Java 字符串对象。若是没法构造该字符串,则为 NULL

抛出:

OutOfMemoryError:若是系统内存不足。

 

6.GetStringUTFLength  -- 获取UTF的String的长度

jsize GetStringUTFLength(JNIEnv *env, jstring string);

Returns the length in bytes of the modified UTF-8 representation of a string.

以字节为单位返回字符串的 UTF-8 长度。

参数:

env:JNI 接口指针。

string:Java 字符串对象。

返回值:

返回字符串的 UTF-8 长度。

 

7.GetStringUTFChars  -- 获取StringUTFChars的指针

const char * GetStringUTFChars(JNIEnv *env, jstring string,jboolean *isCopy);

Returns a pointer to an array of bytes representing the string in modified UTF-8 encoding. This array is valid until it is released by ReleaseStringUTFChars().

If isCopy is not NULL, then *isCopy is set to JNI_TRUE if a copy is made; or it is set to JNI_FALSE if no copy is made.

返回指向字符串的 UTF-8 字符数组的指针。该数组在被ReleaseStringUTFChars() 释放前将一直有效。

若是 isCopy 不是 NULL*isCopy 在复制完成后即被设为 JNI_TRUE。若是未复制,则设为 JNI_FALSE

参数:

env:JNI 接口指针。

string:Java 字符串对象。

isCopy:指向布尔值的指针。

返回值:

指向 UTF-8 字符串的指针。若是操做失败,则为 NULL

 

8.ReleaseStringUTFChars -- 释放StringUTFChars

void ReleaseStringUTFChars(JNIEnv *env, jstring string,const char *utf);

Informs the VM that the native code no longer needs access to utf. The utf argument is a pointer derived from string using GetStringUTFChars().

通知虚拟机平台相关代码无需再访问 utfutf 参数是一个指针,可利用 GetStringUTFChars() 从 string 得到。

参数:

env:JNI 接口指针。

string:Java 字符串对象。

utf:指向 UTF-8 字符串的指针。

Note

In JDK/JRE 1.1, programmers can get primitive array elements in a user-supplied buffer. As of JDK/JRE 1.2 additional set of functions are provided allowing native code to obtain characters in Unicode (UTF-16) or modified UTF-8 encoding in a user-supplied buffer. See the functions below.

注意:

在JDK/JRE 1.1,程序员能够在用户提供的缓冲区获取基本类型数组元素。从JDK/JRE1.2以后,提供了额外的方法,这些方法容许在用户提供的缓冲区获取Unicode字符(UTF-16编码)或者是UTF-8的字符。这些方法详见以下:

 

9.GetStringUTFRegion

void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);

Copies len number of Unicode characters beginning at offset start to the given buffer buf.

Throws StringIndexOutOfBoundsException on index overflow.

在str(Unicode字符)从start位置开始截取len长度放置到buf中。

抛出StringIndexOutOfBoundsException异常。

 

10.GetStringUTFRegion

void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, char *buf);

Translates len number of Unicode characters beginning at offset start into modified UTF-8 encoding and place the result in the given buffer buf.

Throws StringIndexOutOfBoundsException on index overflow.

将str(Unicode字符)从start位置开始截取len长度转换为改良的UTF-8编码并将结果放置到buf中。

抛出StringIndexOutOfBoundsException异常。

 

11.GetStringCritical  /  ReleaseStringCritical

const jchar * GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy);

 

void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *carray);

The semantics of these two functions are similar to the existing Get/ReleaseStringChars functions. If possible, the VM returns a pointer to string elements; otherwise, a copy is made. However, there are significant restrictions on how these functions can be used. In a code segment enclosed by Get/ReleaseStringCritical calls, the native code must not issue arbitrary JNI calls, or cause the current thread to block.

The restrictions on Get/ReleaseStringCritical are similar to those on Get/ReleasePrimitiveArrayCritical.

 

这两个函数的语义是相似于现有的 Get/ReleaseStringChars 功能。若是可能的话,虚拟机返回一个指向字符串元素的指针;不然,将返回一个复制的副本。然而使用这些方法是有值得注意的限制的。In a code segment enclosed by Get/ReleaseStringCritical calls, the native code must not issue arbitrary JNI calls, or cause the current thread to block.

备注

为了提升JVM返回字符串直接指针的可能性,JDK1.2中引入了一对新函数,Get/ReleaseStringCritical。表面上,它们和Get/ReleaseStringChars函数差很少,但实际上这两个函数在使用有很大的限制。

使用这两个函数时,你必须两个函数中间的代码是运行在"critical region"(临界区)的,即,这两个函数中间的本地代码不能调用任何会让线程阻塞或等待JVM中的其它线程的本地函数或JNI函数。

有了这些限制, JVM就能够在本地方法持有一个从GetStringCritical获得的字符串的直接指针时禁止GC。当GC被禁止时,任何线程若是触发GC的话,都会被阻塞。而Get/ReleaseStringCritical这两个函数中间的任何本地代码都不能够执行会致使阻塞的调用或者为新对象在JVM中分配内存。不然,JVM有可能死锁,想象一下这样的场景中:

一、 只有当前线程触发的GC完成阻塞并释放GC时,由其它线程触发的GC才可能由阻塞中释放出来继续运行。

二、 在这个过程当中,当前线程会一直阻塞。由于任何阻塞性调用都须要获取一个正被其它线程持有的锁,而其它线程正等待GC。

Get/ReleaseStringCritical的交迭调用是安全的,这种状况下,它们的使用必须有严格的顺序限制。并且,咱们必定要记住检查是否由于内存溢出而致使它的返回值是NULL。由于JVM在执行GetStringCritical这个函数时,仍有发生数据复制的可能性,尤为是当JVM内部存储的数组不连续时,为了返回一个指向连续内存空间的指针,JVM必须复制全部数据。

总之,为了不死锁,在Get/ReleaseStringCritical之间不要调用任何JNI函数。Get/ReleaseStringCritical和 Get/ReleasePrimitiveArrayCritical这两个函数是能够的。

 

参考资料:

http://blog.csdn.net/mu0206mu/article/details/7182010

http://blog.csdn.net/a345017062/article/details/8068917

相关文章
相关标签/搜索