jni 调用java类方法_AndroidJNI 通过C++调用JAVA
1. JNIEnv对象
对于本地函数
JNIEXPORT void JNICALL Java_video1_TestNative_sayHello(JNIEnv * env, jobject obj)
{
cout<
}
JNIEnv类型代表Java环境。通过这个JNIEnv*指针,就可以对Java端的代码进行操作。如,创建Java类得对象,调用Java对象的方法,获取Java对象的属性等。
JNIEnv的指针会被JNI传送到本地方法的实现函数中来对Java端的代码进行操作
JNIEnv类中的函数:
NewObject/NewString/NewArray :new新对象
Get/SetField:获取属性
Get/SetStaticField :获取静态属性
CallMethod/CallStaticMethod:调用方法
2. Java数据类型与C/C++数据类型的对应关系
可以参考jni.h文件:http://home.pacifier.com/~mmead/jni/cs510ajp/jni.h
Java类型 别名 C++本地类型 字节(bit)
boolean jboolean unsignedchar 8, unsigned
bytejbyte signedchar 8
charjchar unsignedshort 16, unsigned
shortjshortshort 16
intjintlong 32
longjlong __int6464
floatjfloatfloat32
doublejdoubledouble 64
void voidn/a
Object _jobject *jobject
3. 获取jclass
为了能够在C/C++使用Java类,jni.h头文件中专门定义了jclass类型来表示Java中的Class类
jclass的取得:
JNIEnv类中有如下几个简单的函数可以取得jclass
jclass FindClass(const char* clsName) 根据类名来查找一个类,完整类名。
jclass GetObjectClass(jobject obj) 根据一个对象,获取该对象的类
jclass GetSuperClass(jclass obj) 获取一个类的父类
FindClass 会在classpath系统环境变量下寻找类,需要传入完整的类名,注意包与包之间是用"/"而不是"."来分割
如:jclass cls_string= env->FindClass("java/lang/String");
获取jclass又什么用,比如你要调用类的静态方法,静态属性就需要通过这个方法来获取一个类。
4. 本地代码访问Java类中的属性与方法
有了类和对象之后,如何才能访问java中的对象的属性和方法呢,这就需要用到以下这些方法了。
JNI在jni.h头文件中定义了jfieldID,jmethodID类表示Java端的属性和方法
如何获取属性: 在访问或设置Java属性的时候,首先就要现在本地代码中取得代表Java属性的jfieldID,然后才能在本地代码中进行Java属性操作。
如何调用java的方法:调用Java端的方法时,需要取得代表方法的jmethodID才能进行Java方法调用
JNIEnv获取相应的fieldID和jmethodID的方法:
GetFieldID/GetMethodID
GetStaticFieldID/GetStaticMethodID
GetMethodID也可以取得构造函数的jmethodID。创建Java对象时调用指定的构造函数。
如:env->GetMethodID(data_Clazz,"method_name","()V")
(*jniEnv)->GetMethodID(jniEnv, Clazz,"", "()V");
这个比较特殊,这个是默认构造函数的方法,一般用这个来初始化对象,但是再实际过程中,为了快速生成一个实例,一般通过工厂方法类创建jobject
jni.h 对GetMethodID的定义:
jmethodID (JNICALL *GetMethodID)
(JNIEnv *env, jclass clazz, const char *name, const char *sig);
这就引入了一个新的问题,什么是sig,我们后面再说,举个例子说明
前提说明: JAVA类TestProvider,该类有2个方法分别为String getTime( ),void saysayHello( String str)
jclass TestProvider;
jobject mTestProvider;
jmethodID getTime;
jmethodID sayHello;
C 中映射类
TestProvider = (*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");
C中新建对象
//默认构造函数,不传参数 jmethodID construction_id = (*jniEnv)->GetMethodID(jniEnv, TestProvider,"", "()V");
//通过NewObject来创建对象 jobject mTestProvider = (*jniEnv)->NewObject(jniEnv, TestProvider,construction_id);
C 中映射方法
静态:
getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestProvider, "getTime","()Ljava/lang/String;");
非静态:
sayHello = (*jniEnv)->GetMethodID(jniEnv, TestProvider, "sayHello","(Ljava/lang/String;)V");
C 中调用 Java的 方法
静态:
(*jniEnv)->CallStaticObjectMethod(jniEnv, TestProvider, getTime);
非静态:
(*jniEnv)->CallVoidMethod(jniEnv, mTestProvider, sayHello,jstrMSG);
注意GetXXXMethodID 和 CallXXXMethod 。
第一个XXX 表示的是映射方法的类型,如: 静态 跟非静态
第二个 XXX 表示 调用方法的返回值 ,如:Void,Object,等等。(调用静态方法的时候Call后面要加Static)
5. sign签名
对于jmethodID GetMethodID(jclass clazz, const char *name, const char *sign)
clazz代表该属性所在的类,name表示方法名称,sign是签名
那什么是签名,签名是对函数参数和返回值的描述,对同一个函数,在java中允许重载,这个时候就需要这个sign来进行区分了。
以下是java类型签名的描述
用来表示要取得的属性/方法的类型
类型 相应的签名
boolean Z
byteB
charC
shortS
intI
longJ
floatF
doubleD
voidV
objectL用/分隔包的完整类名: Ljava/lang/String;
Array [签名 [I [Ljava/lang/Object;
Method (参数1类型签名 参数2类型签名···)返回值类型签名
特别注意:Object后面一定有分号(;)结束的,多个对象参数中间也用分号(;)来分隔
例子:
方法签名
voidf1() ()V
intf2(int,long) (IJ)I
boolean f3(int[]) ([I)B
doublef4(String,int) (Ljava/lang/String;I)D
voidf5(int, String [],char) (I[Ljava/lang/String;C)V
图解签名:
使用javap命令来产生签名
javap -s -p [full class Name]
-s 表示输出签名信息
-p 同-private,输出包括private访问权限的成员信息
例子:
C:\E\java\workspaces\myeclipseblue\JNITest\bin>javap -s -private video1.TestNative
Compiled from "TestNative.java"
public class video1.TestNative extends java.lang.Object{
public java.lang.String name;
Signature: Ljava/lang/String;
public video1.TestNative();
Signature: ()V
public int signTest(int, java.util.Date, int[]);
Signature: (ILjava/util/Date;[I)I
public native void sayHello();
Signature: ()V
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
}
TestNative完整代码:
package video1;
import java.util.Date;
public class TestNative {
public String name="Test";
public int number =100;
public int signTest(int i,Date date,int[] arr){
System.out.println("Sign Test");
return 0;
}
//native关键字修饰的方法,其内容是C/C++编写的,java中不必为它编写具体的实现 public native void sayHello();
public static void main(String[] args) {
System.loadLibrary("NativeCode");
TestNative tn = new TestNative();
tn.sayHello();
}
}
C/C++代码
#include "video1_TestNative.h"
#include
using namespace std;
JNIEXPORT void JNICALL Java_video1_TestNative_sayHello(JNIEnv * env, jobject obj){
cout<
//因为test不是静态函数,所以传进来的就是调用这个函数的对象//否则就传入一个jclass对象表示native()方法所在的类 jclass native_clazz = env->GetObjectClass(obj);
//得到jfieldID jfieldID fieldID_prop = env->GetFieldID(native_clazz,"name","Ljava/lang/String;");
jfieldID fieldID_num = env->GetFieldID(native_clazz,"number","I");
//得到jmethodID jmethodID methodID_func=env->GetMethodID(native_clazz,"signTest","(ILjava/util/Date;[I)I");
//调用signTest方法 env->CallIntMethod(obj,methodID_func,1L,NULL,NULL);
//得到name属性 jobject name = env->GetObjectField(obj,fieldID_name);
//得到number属性 jint number= env->GetIntField(obj,fieldID_num);
cout<SetIntField(obj,fieldID_num,18880L);
number= env->GetIntField(obj,fieldID_num);
cout<
本文地址,转载请注明出处:
参考资料:
jni.h 头文件:
相关例子:
Programmming in C/C++ with the Java Native Interface (3 个练习)
JNI 文档:
基于 Android NDK 的学习之旅----- C调用Java
Linux下JNI的使用:比较基础
如何在Android下使用JNI:讲解比较详细,但是代码里有些错误,空格没处理好
这篇文章有些地方不清楚的参考下这篇文章
Android Jni代码示例讲解
其他推荐学习网站
使用 Java Native Interface 的最佳实践:描述了JNI性能和缓存的一些东西
JNI 攻略系列
JNI Examples for Android
JNI pthread 多线程使用
jni 调用java类方法_AndroidJNI 通过C++调用JAVA相关推荐
- java类方法不可见_使java方法仅对特定类可见
我有一个经理类负责管理某种对象.要做到这一点,它需要操纵这些对象,但这些对象与管理器无关,所以从技术上讲,它们位于单独的包"project.managers"和"proj ...
- java在主程序修改函数输出,Java通过JNI调用CUDA
--NG 这段时间因为工作需要,要用到在java中调用cuda程序,但是令人蛋疼的是网上这方面的资料几乎没有,所以只好我自己摸索.我的想法是通过java的JNI接口调用cuda,但是很明显正常情况下是 ...
- java JNI调用C语言动态链接库(java.lang.UnsatisfiedLinkError: no yourClassName in java.library.path 异常的解决方法)
转自: http://watershitter.iteye.com/blog/477615 今天花了至少3个小时跑这个java调c的动态链接库的Hello,native world的程序. 把所有犯 ...
- jni c java互相调用_通过JNI实现Java和C++的相互调用
评论 # re: 通过JNI实现Java和C++的相互调用 2008-07-29 14:14 Always BaNg. 不错,把字符转换也一并讲了吧,比如UTF-8的处理,USC-2与MBCS转换等. ...
- cocos2d-x 调用java_cocos2d-x中通过Jni实现Java与C++的互相调用
cocos2d-x中通过Jni实现Java与C++的互相调用. cocos2d-x用开发者提供了一个类JniHelper,提供了java与c++之间互调的jni解决方案. 笔者所开发的"史上 ...
- Android JNI实现Java与C/C++互相调用,以及so库的生成和调用(JNI方式调用美图秀秀so)
前言 关于Android Studio如何继承JNI开发环境,请阅读上一篇博文 Android CMake集成JNI开发环境本篇博文将结合实例分别讲解Android中Java如何调用C/C++的方法, ...
- java 实例方法直接调用超类的实例方法_类方法和实例方法的调用 super this 访问控制符...
一.类方法和实例方法的调用 先看一道选择题: 下列哪种说法是正确的( ) A. 实例方法可直接调用超类的实例方法 B. 实例方法可直接调用超类的类方法 C. 实例方法可直接调用其他类的实例方法 D. ...
- beetl调用java方法_08.自定义方法以及直接访问java类方法---《Beetl视频课程》
本期视频实现了发布评论时间自定义显示: 内容简介:使用了自定义方法以及直接访问java方法实现了发布时间自定义显示 作者:GK 自定义方法 我们想要实现类似于${ strutil.subString ...
- Java——this关键字(调用本类属性、调用本类方法、表示当前对象)
目录 1.调用本类属性 2.调用本类方法 3.表示当前对象 this是一个非常灵活的关键字,不会明确表示一个固定概念,比如int,它就是表示一个整型. 1.调用本类属性 类中有许多成员,大部分情况下类 ...
- java 类方法和实例方法 调用关系
java 类方法和实例方法 1. 类方法 也可称静态方法,使用static修饰的类中方法: 2.实例方法 非静态方法,没有用static修饰的方法. 3.测试案例 public class Test ...
最新文章
- Foxmail邮件如何导入Outlook中
- 【Python小程序】必备软件系列之文字识别提取,前台再也不同担心纸质转电子文件啦~
- 防止mysql拷贝_转载:mysql复制优化
- 查一个字段中字符集超过30的列_详细解读MySQL的30条军规
- mb_internal_encoding php,PHP字符串mbstring处理中文字符串的具体方法解析
- 通过Intel XDK编写跨平台app(一)
- Java面试官最爱问的垃圾回收机制,Java编程配置思路详解
- 1631. 最小体力消耗路径
- Xcode真机调试中“There was an internal API error“错误解决方法
- 读《scikiit-learn机器学习》黄永昌第四章
- WIN7下IIS的安装与配置
- Java web技术及应用答案_超星《Java Web应用开发技术》答案
- paip.c#.net未能找到任何资源
- yml在线格式转换工具
- 冷暖自知 who knew:伤感日志
- 从 Uber 数据泄露事件我们可以学到什么?
- JS中字符串的创建、操作及其方法
- 一个int类型到底占多少个字节
- Linux查看系统信息命令总结
- dlib.get_frontal_facedetector UINT8 和float格式互相转换
热门文章
- 逐步揭示makop.mkp勒索病毒中毒防范恢复解密
- cubemx6.0配置touchgfx 正点原子触摸屏,touchgfx添加触摸驱动
- 安卓10源码开发定制(30)screencap命令源码分析
- 桌面运维转网络要做什么准备,高级网工学习路线分享
- 计算机桌面维护的相关知识,电脑维护知识
- ERP : 服装行业解决方案
- java图片转为矢量文件_java 通过batik 把svg格式的矢量图生成png图片
- Android音频播放之SoundPool 详解
- 操作系统 | 内存文件映射 —— 文件到内存的映射
- 完整制作个人博客系统