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

以下文档来自官方:

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字符均可以被表示出来。

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还是有区别的。

参数

env:JNI 接口指针。

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有可能死锁,想象一下这样的场景中:

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

2、 在这个过程中,当前线程会一直阻塞。因为任何阻塞性调用都需要获取一个正被其它线程持有的锁,而其它线程正等待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

JNI之String类型的更多相关文章

  1. JNI中java类型的简写

      在JNI中,当我们使用GetFieldID/GetStaticFieldID或GetMethodID/GetStaticMethodID及定义JNINativeMethod等时,我们需要表示成员变 ...

  2. ElasticSearch 5学习(9)——映射和分析(string类型废弃)

    在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...

  3. 每日一记-mybatis碰到的疑惑:String类型可以传入多个参数吗

    碰到一个觉得很疑惑的问题,Mybatis的parameterType为String类型的时候,能够接收多个参数的吗? 背景 初学Mybatis的时候,看的教程和书籍上都是在说基本的数据类型如:int. ...

  4. C#string类型总结

    字符串的特性:不可变性,每对字符串做拼接或者重新赋值之类的操作,都会在内存中产生一个新的实例.  所以说,在.Net平台下,如果你对一个字符串进行大量的拼接赋值等操作,会产生大量的垃圾.    --- ...

  5. 把《c++ primer》读薄(3-1 标准库string类型初探)

    督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 问题1:养成一个好习惯,在头文件中只定义确实需要的东西 using namespace std; //建议需要什么再using声 ...

  6. 【原创】Java和C#下String类型中的==和equals的原理与区别

    一.Java下 1.几个例子 public static void main(String[] arge) { String str1 = new String("1234"); ...

  7. String类型的属性和方法

    × 目录 [1]属性 [2]对象通用方法 [3]访问字符方法[4]字符串拼接[5]创建子串方法[6]大小写转换[7]查找子串位置[8]正则匹配方法[9]去除首尾空格[10]字符串比较 前面的话 前面已 ...

  8. String类型传值以及对象传值

    package Virtual; class Stan{ String mm = "hello"; } class Virtual { public static void mai ...

  9. java动手动脑和课后实验型问题String类型

    1.请运行以下示例代码StringPool.java,查看其输出结果.如何解释这样的输出结果?从中你能总结出什么? true true false 总结: 使用new关键字创建字符串对象时, 每次申请 ...

随机推荐

  1. Git与GitHub学习笔记(三).gitignore文件忽略和删除本地以及远程文件

    一.Git提供了文件忽略功能.当对工作区某个目录或者某些文件设置了忽略后,git将不会对它们进行追踪 HELP:如何在IntelliJ IDEA中使用.ignore插件忽略不必要提交的文件 问题:最近 ...

  2. 编写 grunt 插件经验

    第一步: 先生成插件模板: 利用命令生成, 首先通过github工具获取gruntplugin模板文件: 第二步: 了解plugin/tasks/taskName.js的registerMultiTa ...

  3. 【51Nod】1273 旅行计划 树上贪心

    [题目]51Nod 1273 旅行计划 [题意]给定n个点的树和出发点k,要求每次选择一个目的地旅行后返回,使得路径上未访问过的点最多(相同取编号最小),旅行后路径上所有点视为访问过,求旅行方案.\( ...

  4. 【项目部署】部署项目以war包部署和解开以目录部署的区别

    我们都知道最简单的部署web项目的方式是打成war包直接仍在tomcat的webapps目录下,我上个项目也确实是这样做的,可是这给我们后期的维护带来了极大的不便,下面就简单研究一下以war包部署和解 ...

  5. Virut.ce-感染型病毒分析报告

    1.样本概况 病毒名称 Virus.Win32.Virut.ce MD5 6A500B42FC27CC5546079138370C492F 文件大小 131 KB (134,144 字节) 壳信息 无 ...

  6. python3之模块urllib

    urllib是python内置的HTTP请求库,无需安装即可使用,它包含了4个模块: request:它是最基本的http请求模块,用来模拟发送请求 error:异常处理模块,如果出现错误可以捕获这些 ...

  7. mount过程分析之一(基于3.16.3内核)【转】

    转自:https://blog.csdn.net/zr_lang/article/details/39963253 一直想写有些关于文件系统的博文,但是由于近一年来实在太忙,所以没有时间写.前几日赶上 ...

  8. python报错IndexError: list index out of range

    今天写个ping vpn的python脚本,报错IndexError: list index out of range 最后查看是python读取文件中出现空格 去掉空格即可

  9. MySQL5.7 GTID在线开启与关闭【转】

    当前场景   当前某些业务还有未开启GTID服务组,升级5.7后,如何检测是否符合开启GTID条件,如何在线修改切换使用GTID:已经升级5.7后,已经开启GTID,如何快速回滚后退: 线上gtid如 ...

  10. java Foreach与迭代器

    foreach语法主要用于数组,但是它也可以用于Collection对象,下面是一个示例 package object; //: holding/ForEachCollections.java // ...