- 浏览: 66106 次
- 性别:
- 来自: 江苏
文章分类
最新评论
-
donghustone:
楼主好强大!!
resin2.1.17 官方下载地址 -
MultiArrow:
这么说的话好像就只有CentOS没有一个比较强的企业在使用。。 ...
诸多linux,但选一个做服务器
JNI 的类型和数据结构
Java 类型 本地类型 说明
boolean jboolean 无符号,8 位
byte jbyte 无符号,8 位
char jchar 无符号,16 位
short jshort 有符号,16 位
int jint 有符号,32 位
long jlong 有符号,64 位
float jfloat 32 位
double jdouble 64 位
void void N/A
由于JVM中,使用统一的UTF-8编码,java传入的String参数,在c文件中被jni转换为jstring的数据类型,在c文件中声明char* psz,然后psz = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);c++的操作简单些,env->GetStringUTFChars( jstring, NULL);注意使用完后,运行(*env)->ReleaseStringUTFChars(env, jstring, psz);
将一个c的字符串转为jstring,
static char lastfile[80];
JNIEXPORT jstring JNICALL Java_ReadFile_lastFile
(JNIEnv *env, jobject jobj) {
return((*env)->NewStringUTF(env, lastfile));
}
例子
JNIEXPORT jstring JNICALL
Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const jbyte *str;
str = (*env)->GetStringUTFChars(env, prompt, NULL);
if (str == NULL) {
return NULL; /* OutOfMemoryError already thrown */
}
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str);
/* We assume here that the user does not type more than
* 127 characters */
scanf("%s", buf);
return (*env)->NewStringUTF(env, buf);
}
如果使用Unicode编码,不需要使用UTF-8处理,使用如下方法
JNIEXPORT jbyteArray JNICALL Java_ReadFile_loadFile
(JNIEnv * env, jobject jobj, jstring name) {
caddr_t m;
jbyteArray jb;
struct stat finfo;
jboolean iscopy;
const jchar *mfile = (*env)->GetStringChars(env,
name, &iscopy);
//...
(*env)->ReleaseStringChars(env, name, mfile);
传递Array
boolean
public static void setArray( boolean[] ba )
{
for( int i=0; i < ba.length; i++ )
ba[i] = true;
setArray0( ba );
}
private static native void setArray0( boolean[] ba );
布尔型数组被初始化为 true,本地方法将把特定的元素设置为 false。同时,在 Java 源代码中,我们可以更改 main 以使其包含测试代码:
boolean[] ba = new boolean[5];
MyNative.setArray( ba );
for( int i=0; i < ba.length; i++ )
System.out.println( ba[i] );
在编译源代码并执行 javah 以后,MyNative.h 头文件包含以下的原型:
/*
* Class: MyNative
* Method: setArray0
* Signature: ([Z)V
*/
JNIEXPORT void JNICALL Java_MyNative_setArray0
(JNIEnv *, jclass, jbooleanArray);
布尔型数组是作为单个名为 jbooleanArray 的类型创建的。
基本类型有它们自已的数组类型,如 jintArray 和 jcharArray。
非基本类型的数组使用 jobjectArray 类型。下一个示例中包括一个 jobjectArray。这个布尔数组的数组元素是通过 JNI 方法 GetBooleanArrayElements 来访问的。
针对每种基本类型都有等价的方法。这个本地方法是如下实现的:
JNIEXPORT void JNICALL Java_MyNative_setArray0
(JNIEnv *env, jclass cls, jbooleanArray ba)
{
jboolean* pba = (*env)->GetBooleanArrayElements( env, ba, 0 );
jsize len = (*env)->GetArrayLength(env, ba);
int i=0;
// 更改偶数数组元素
for( i=0; i < len; i+=2 )
pba[i] = JNI_FALSE;
(*env)->ReleaseBooleanArrayElements( env, ba, pba, 0 );
}
指向布尔型数组的指针可以使用 GetBooleanArrayElements 获得。
数组大小可以用 GetArrayLength 方法获得。使用 ReleaseBooleanArrayElements 方法释放数组。就可以读取和修改数组元素的值了。
int 数组
class IntArray {
private native int sumArray(int[] arr);
public static void main(String[] args) {
IntArray p = new IntArray();
int arr[] = new int[10];
for (int i = 0; i < 10; i++) {
arr[i] = i;
}
int sum = p.sumArray(arr);
System.out.println("sum = " + sum);
}
static {
System.loadLibrary("jnistudy");
}
}
jni的c程序
#include <jni.h>
#include <stdio.h>
#include "IntArray.h"
JNIEXPORT jint JNICALL
Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jint *carr;
jint i, sum = 0;
carr = (*env)->GetIntArrayElements(env, arr, NULL);
if (carr == NULL) {
return 0; /* exception occurred */
}
for (i=0; i<10; i++) {
sum += carr[i];
}
(*env)->ReleaseIntArrayElements(env, arr, carr, 0);
return sum;
}
GetIntArrayRegion得到数组,ReleaseIntArrayElements释放资源,GetArrayLength得到数组的长度,SetIntArrayRegion修改数组元素的值。
多位int 数组
class ObjectArrayTest {
private static native int[][] initInt2DArray(int size);
public static void main(String[] args) {
int[][] i2arr = initInt2DArray(3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(" " + i2arr[i][j]);
}
System.out.println();
}
}
static {
System.loadLibrary("jnistudy");
}
}
jni的代码
#include <jni.h>
#include <stdio.h>
#include "ObjectArrayTest.h"
JNIEXPORT jobjectArray JNICALL
Java_ObjectArrayTest_initInt2DArray(JNIEnv *env,
jclass cls,
jint size)
{
jobjectArray result;
int i;
jclass intArrCls = (*env)->FindClass(env, "[I");
if (intArrCls == NULL) {
return NULL; /* exception thrown */
}
result = (*env)->NewObjectArray(env, size, intArrCls, NULL);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
for (i = 0; i < size; i++) {
jint tmp[256]; /* make sure it is large enough! */
int j;
jintArray iarr = (*env)->NewIntArray(env, size);
if (iarr == NULL) {
return NULL; /* out of memory error thrown */
}
for (j = 0; j < size; j++) {
tmp[j] = i + j;
}
(*env)->SetIntArrayRegion(env, iarr, 0, size, tmp);
(*env)->SetObjectArrayElement(env, result, i, iarr);
(*env)->DeleteLocalRef(env, iarr);
}
return result;
}
Get/SetObjectArrayElement得到和设置数组的元素的值。
传递 Java String 数组
本例将通过最常用的非基本类型,Java String,说明如何访问非基本对象的数组。字符串数组被传递给本地方法,而本地方法只是将它们显示到控制台上。
MyNative 类定义中添加了以下几个方法:
public static void showStrings( String[] sa )
{
showStrings0( sa );
}
private static void showStrings0( String[] sa );
测试
String[] sa = new String[] { "Hello,", "world!", "JNI", "is", "fun." };
MyNative.showStrings( sa );
c代码中,本地方法分别访问每个元素,
JNIEXPORT void JNICALL Java_MyNative_showStrings0
(JNIEnv *env, jclass cls, jobjectArray sa)
{
int len = (*env)->GetArrayLength( env, sa );
int i=0;
for( i=0; i < len; i++ )
{
jobject obj = (*env)->GetObjectArrayElement(env, sa, i);
jstring str = (jstring)obj;
const char* szStr = (*env)->GetStringUTFChars( env, str, 0 );
printf( "%s ", szStr );
(*env)->ReleaseStringUTFChars( env, str, szStr );
}
printf( "\n" );
}
数组元素可以通过 GetObjectArrayElement 访问。 因为返回值是 jstring 类型,所以可以安全地将它从 jobject 类型转换为 jstring 类型。
返回 Java String 数组
在本地代码中创建一个字符串数组并将它返回给 Java 调用者。MyNative.java 中添加了以下几个方法:
public static String[] getStrings()
{
return getStrings0();
}
private static native String[] getStrings0();
使用showStrings 将 getStrings 的输出显示出来:
MyNative.showStrings( MyNative.getStrings() );
实现的本地方法返回五个字符串。
JNIEXPORT jobjectArray JNICALL Java_MyNative_getStrings0
(JNIEnv *env, jclass cls)
{
jstring str;
jobjectArray args = 0;
jsize len = 5;
char* sa[] = { "Hello,", "world!", "JNI", "is", "fun" };
int i=0;
args = (*env)->NewObjectArray(env, len, (*env)->FindClass(env, "java/lang/String"), 0);
for( i=0; i < len; i++ )
{
str = (*env)->NewStringUTF( env, sa[i] );
(*env)->SetObjectArrayElement(env, args, i, str);
}
return args;
}
字符串数组是通过调用 NewObjectArray 创建的,同时传递了 String 类和数组长度两个参数。Java String 是使用 NewStringUTF 创建的。String 元素是使用 SetObjectArrayElement 存入数组中的。
另外要通过jni来改变java的参数引用,例如有参数jbyteArray account,修改完account的值后,java要获取该值,直接使用
jbyte* jbAccount = (env)->GetByteArrayElements(env, account, 0);
char* szAccount = (char*)jbAccount;
指针的地址并不是account的地址,最后赋下值才行
env->SetByteArrayRegion(account,0,strlen(szAccount),jbyte* jbAccount);
发表评论
-
java的社区网站不是用java写的,俺觉得很讽刺
2010-10-17 14:52 882java的技术社区网站不是用java写的,俺觉得很讽刺~~~ -
用户IP地址的三个属性的区别(HTTP_X_FORWARDED_FOR,HTTP_VIA,REM_addr
2009-10-09 18:06 1511一、没有使用代理服务器的情况: REMOTE_ ... -
【ibatis】动态结果集 类型映射
2009-10-20 10:58 1442ibatis的动态结果使用 java.util.HashMap ... -
ConcurrentHashMap应用注意事项
2010-04-13 09:23 17941、public V get(Object key)不涉及到锁 ... -
【转】网络字节序与主机字节序
2010-04-15 10:37 2217最近在项目开发过程中,需要在采用JAVA作为语言的服务器与采用 ... -
【转】在Java与C程序间进行socket通信的讨论
2010-04-15 13:29 11741. 背景 使用socket在Java程序与C程序间进行进 ... -
【转】单例模式不可使用双重检查锁定
2010-04-21 00:49 1131转自:http://www.ibm.com/develope ... -
四个有用的过虑器
2010-04-24 16:36 672一、使浏览器不缓存页面的过滤器 import javax.se ... -
汉字字符编码与转码详解
2010-04-26 14:03 819程序中有汉字参数,经常会遇到编码转码问题,总结下: 1.汉字为 ... -
java dom4j操作xml
2010-05-22 18:26 827java dom4j操作xml SAXReader reade ... -
jni javac++ 参数传递问题解决
2010-05-23 13:18 1229一,问题 1.多参数回传 2.参数传递出现乱码 二,解决 ... -
汉字字符编码与转码详解
2010-05-23 13:19 854程序中有汉字参数,经常会遇到编码转码问题,总结下: 1.汉字为 ...
相关推荐
### jni需要注意的常见问题 #### 一、输入问题 在使用 JNI (Java Native Interface) 进行开发时,输入问题往往会被忽视但同样非常重要。尤其是当涉及到 C 或 C++ 的 `.c` 或 `.cpp` 文件时,由于不同平台间的编码...
在使用JNI开发时,理解这些注意事项是至关重要的,能够帮助避免许多潜在的问题和错误,确保本地代码和Java代码之间的无缝交互。同时,使用JNI还涉及到线程安全、错误处理和性能优化等多个方面,这些都是开发者在实践...
在实际开发中,还需要注意一些细节,比如错误处理、内存管理(Java对象在本地代码中使用需要通过JNI函数创建和释放)、线程安全问题等。同时,由于涉及到跨语言和跨平台,理解JNI的工作原理和正确使用JNI头文件至关...
在DLL中,我们还需要注意线程安全问题。如果多个Java线程同时调用DLL中的函数,可能需要使用线程局部存储(TLS)或者其他同步机制来防止数据冲突。 在Java端,我们需要加载并初始化DLL。可以使用`System....
此外,还要注意线程安全问题,因为Java是多线程的,而Delphi的代码可能需要同步控制以避免竞态条件。 总结来说,`jni.pas`和`JNI_MD.INC`是Delphi开发者使用JNI的关键组件,它们使得Delphi程序能够无缝地与Java世界...
文档"JNI传递中文字符串.doc"和"jni的中文字符串处理.doc"将更深入地探讨这些主题,包括示例代码、最佳实践以及可能遇到的问题及解决方案。通过学习这些文档,开发者将能够熟练地在JNI环境中处理包含中文的字符串,...
JNI中的内存管理需要注意,因为Java和C/C++的内存模型不同。在本地代码中分配的内存需要在本地代码中释放,反之亦然。此外,JNI提供了引用计数机制,用于管理Java对象在本地代码中的生命周期。 7. **错误处理和...
- **线程安全**:Java是多线程的,而C/C++可能不支持,所以在JNI代码中要处理好线程同步问题。 - **异常处理**:JNI调用中出现错误时,可能需要通过抛出Java异常来通知Java层。 - **平台兼容性**:本地代码必须...
要实现“安卓中实现JNI读取内存信息”,我们需要以下步骤: 1. **创建JNI头文件(.h)**:在Java源代码中,我们使用`native`关键字声明一个方法,比如`getMemoryInfo()`,然后使用`javah`工具生成对应的C++头文件。...
注意,由于Java对象不能直接在JNI中跨线程使用,因此如果要在C/C++中存储或操作Java对象,通常需要将对象序列化为基本类型(如整数或字符串)。对于复杂的对象,可能需要自定义序列化和反序列化逻辑。 5. **内存...
用 JNI 调用本地接口 作 者 : nxy1027@163.com在本文中,我们将深入探讨如何使用JNI(Java Native Interface)来调用本地接口,特别是在处理中文字符串时遇到的挑战。JNI是Java平台提供的一种机制,允许Java代码与...
### 在JNI中获取Android设备IMEI号的方法 #### 背景介绍 在移动应用开发过程中,有时我们需要获取Android设备的一些基本信息,例如IMEI(International Mobile Equipment Identity)号,这是一串由15位数字组成的...
在Android开发中,JNI(Java Native Interface)是一个关键的技术,它允许Java代码和其他语言写的代码进行交互。JNI在很多场景下都非常有用,比如优化性能、使用现有的C/C++库、或者像在这个“JniCallback.zip”文件...
值得注意的是,JNI虽然强大,但也有其局限性和潜在的问题。例如,由于涉及到本地代码,调试起来可能较为复杂,且本地方法不享受Java的垃圾收集机制,需要手动管理内存。此外,过度使用JNI可能导致代码可移植性降低。...
6. **线程安全**:在Android 5.0中,JNI函数默认运行在主线程之外,开发者需要注意多线程环境下的同步问题。正确地管理和同步本地资源,避免数据竞争,是保证应用稳定的关键。 7. **错误处理**:Android 5.0提供了...
在实际应用中,需要注意线程安全问题,特别是当JNI线程需要访问Java对象时。因为Java对象在不同线程间通常是不可直接共享的,需要进行适当的同步操作,如使用`MonitorEnter`和`MonitorExit`。此外,由于Java虚拟机会...
这个过程中有几个需要注意的点: 1. 错误处理:JNI操作可能会抛出异常,如找不到类或方法,需要进行适当的错误处理。 2. 内存管理:由于C++和Java的内存管理机制不同,需要谨慎处理字符串和对象的生命周期,避免内存...
Jni应用详解 Jni(Java Native Interface)是一种allowing Java代码与 native 代码集成的技术,使得Java程序能够调用native方法和库。下面是Jni应用的详细解释...然而,Jni也存在一些常见问题,需要开发者注意和解决。
- **性能优化**:由于JNI调用比Java原生调用慢,因此应尽量减少不必要的跨语言调用,例如可以考虑一次性加密大量数据而不是单个字节。 综上所述,"Android中JNI实现AES加密源代码"涉及的知识点包括Android JNI的...
JNI在很多场景下都是必要的,比如当Java需要调用已有的C/C++库,或者想要利用硬件特性,或者优化性能时。这篇文章将深入探讨JNI的核心概念、使用方法以及在实际开发中的应用。 首先,JNI提供了Java虚拟机(JVM)与...