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

相關文章
相關標籤/搜索