2013-08-19 200 views
5

在JNI功能的文檔的findClass我可以閱讀有關參數JNI字符串和C字符串

名稱:該字符串在修改編碼的完全合格的類名(...) UTF-8。

根據文檔改性UTF-8具有雙重「\ 0」字符結束:

空字符(CHAR)0使用兩個字節的格式,而不是一維編碼字節格式

這是否意味着我應該在C以這種方式調用的findClass: FindClass("java/lang/String\0")

即雙「\ 0」在結束了嗎?

+2

當你試過時發生了什麼,它是否起作用? – mah

+0

@mah問題提出「應該」而不是「可能」。這是關於技術的正確性而不是[「通過巧合編程。」](http://pragprog.com/the-pragmatic-programmer/extracts/coincidence)當然,它的工作原理是正確的,但這並不正確。 –

回答

3

字符集,編碼和終止是三個不同的東西。顯然,編碼是爲特定字符集設計的,但字符集可以用多種方式編碼。而且,終結者(如果使用的話)通常是一個編碼字符,但是修改後的UTF-8並非如此。

Java使用Unicode字符集。對於字符串和字符類型,它使用UTF-16編碼。字符串類型被計數;它不使用終止符。

在C中,終止字符串是常見的,以及各種字符集的單字節編碼。 C和C++編譯器用NUL字符結束文字字符串。在編譯器的目標字符集編碼中,這是一個或兩個0x00字節。幾乎所有通用字符集及其編碼都具有非控制ASCII字符的相同字節表示形式。 Unicode字符集的UTF-8編碼也是如此。 (但是,請注意,對於有限子集以外的字符不適用。)

JNI設計人員選擇使用C字符串之間有限的「互操作性」。許多JNI函數接受以0x00結尾的修改的 UTF-8字符串。它們與源代碼中的文字字符串所產生的C編譯器兼容,同樣規定字符限制爲非控制ASCII字符。這涵蓋了在JNI中編寫Java包&類,方法和字段字符串的用例。 (好吧,幾乎:Java允許標識符中包含任何Unicode貨幣符號。)

因此,您可以將C字符串文字傳遞給所見即所得風格的JNI函數。不需要添加終止符 - 編譯器會這樣做。 C編譯器會將額外的'\ 0'字符編碼爲0x00,所以它不會造成任何傷害,但不是必需的。

對標準UTF-8編碼有一些修改。一種是允許期望0x00終止符能夠「處理」修改的UTF-8字符串的C函數,NUL字符(U + 00000)被編碼以避免0x00,這將是標準。這允許修改後的UTF-8字符串放置在具有0x00終止符的緩衝區之外,超出原始編碼字符串的字節。另一種修改有點深奧,但兩種修改都會使修改後的UTF-8字符串與嚴格符合UTF-8的函數不兼容。

你沒有問,但在JNI中有另一種使用0x00終止,修改的UTF-8字符串。它與GetStringUTFCharsNewStringUTF功能。 (JNI文檔實際上並沒有說GetStringUTFChars返回一個0x00終止的字符串,但沒有已知的JVM實現不支持。請檢查JVM實現者的文檔或源代碼。)這些函數的設計基於相同的「互操作性」。但是,用例是不同的,這使得它們很危險。它們通常用於在C函數之間傳遞Java字符串。一般來說,C函數不知道修改過的UTF-8是什麼,甚至可能甚至不知道UTF-8或Unicode是什麼。使用Java StringCharset類可以更直接地轉換爲C函數專用的字符集和編碼。通常,這是用於確定C函數正在使用的系統設置,用戶設置,應用程序設置或線程設置。 Java String類嘗試在未給定轉換的特定編碼時符合此類設置。但是,在很多情況下,所需的編碼是固定的,並且可以用明確的意圖來指定。

3

不,according to the first reference I found,這意味着它應該像這樣編碼:

FindChar("java/lang/String\xc0\x80"); 
          ^
           | 
           | 
        This is not the shortest 
        way to encode the codepoint 
        U+0000, which is why it's 
        "modified" UTF-8. 

注意,這裏假設你真的在尋找類名,後綴名爲U + 0000,這是相當不可能的。

FindChar("java/lang/String"); 

通過經修訂的UTF-8提供的U + 0000的特殊2字節編碼只,如果你想很重要:當你從剛剛獲得的C字符串應該被終止,就像正常,單0字節把U + 0000放在一個字符串中,並且仍然能夠將它與C終結符區分開來。

3

不,你不要編碼終止零,它不是類名的一部分。