JNI使用的是改良的UTF-8格式的Strings。java
如下文檔來自官方:程序員
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
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()
.
通知虛擬機平臺相關代碼無需再訪問 utf
。utf
參數是一個指針,可利用 GetStringUTFChars()
從 string
得到。
env:JNI 接口指針。
string:Java 字符串對象。
utf
:指向 UTF-8 字符串的指針。
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這兩個函數是能夠的。
參考資料: