JNI 方法注册与签名+BufferedReader使用readLine问题
最近了解了关于JavaJNI接口的一些关于方法注册与签名相关的知识,在此进行一下总结。
使用JNI接口时,我们首先需要把Java方法声明为native:
- public native void f();
然后编写对应的C/C++代码,并编译成为动态链接库(.dll或.so),在调用Java方法前载入动态链接库即可调用:
- static {
- System.loadLibrary("native-lib");
- }
那么,Java文件中的native方法是如何与native文件中的方法一一对应的呢?
在此有两种方法:静态注册与动态注册,下面将一一介绍:
静态注册
- javah -jni 包名.类名
自动生成对应的c层头文件
- package com.app.superxlcr.jnitest;
- /**
- * Created by superxlcr on 2017/5/25.
- */
- public class NativeTest {
- public native void f();
- public native int f(int a, double b);
- public native void f(Object a, String b);
- public native void g();
- }
native层:
- /* DO NOT EDIT THIS FILE - it is machine generated */
- #include <jni.h>
- /* Header for class com_app_superxlcr_jnitest_NativeTest */
- #ifndef _Included_com_app_superxlcr_jnitest_NativeTest
- #define _Included_com_app_superxlcr_jnitest_NativeTest
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*
- * Class: com_app_superxlcr_jnitest_NativeTest
- * Method: f
- * Signature: ()V
- */
- JNIEXPORT void JNICALL Java_com_app_superxlcr_jnitest_NativeTest_f__
- (JNIEnv *, jobject);
- /*
- * Class: com_app_superxlcr_jnitest_NativeTest
- * Method: f
- * Signature: (ID)I
- */
- JNIEXPORT jint JNICALL Java_com_app_superxlcr_jnitest_NativeTest_f__ID
- (JNIEnv *, jobject, jint, jdouble);
- /*
- * Class: com_app_superxlcr_jnitest_NativeTest
- * Method: f
- * Signature: (Ljava/lang/Object;Ljava/lang/String;)V
- */
- JNIEXPORT void JNICALL Java_com_app_superxlcr_jnitest_NativeTest_f__Ljava_lang_Object_2Ljava_lang_String_2
- (JNIEnv *, jobject, jobject, jstring);
- /*
- * Class: com_app_superxlcr_jnitest_NativeTest
- * Method: g
- * Signature: ()V
- */
- JNIEXPORT void JNICALL Java_com_app_superxlcr_jnitest_NativeTest_g
- (JNIEnv *, jobject);
- #ifdef __cplusplus
- }
- #endif
- #endif
我们可以看到,对于拥有重载的f 方法,其native方法名称后都带有参数,而没有重载的g 方法则没带有
动态注册
- typedef struct {
- // Java层native方法名称
- const char* name;
- // 方法签名
- const char* signature;
- // native层方法指针
- void* fnPtr;
- } JNINativeMethod;
然后重写JNI_OnLoad方法(该方法会在Java层通过System.loadLibrary加载完动态链接库后被调用),我们在其中进行动态注册工作:
- JNIEXPORT jint JNICALL
- JNI_OnLoad(JavaVM* vm, void* reserved) {
- JNIEnv *env = NULL;
- jint result = -1;
- // 获取JNI env变量
- if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- // 失败返回-1
- return result;
- }
- // 获取native方法所在类
- const char* className = "com/app/superxlcr/jnitest/MainActivity";
- jclass clazz = env->FindClass(className);
- if (clazz == NULL) {
- return result;
- }
- // 动态注册native方法
- if (env->RegisterNatives(clazz, methods, 1) < 0) {
- return result;
- }
- // 返回成功
- result = JNI_VERSION_1_4;
- return result;
- }
动态注册的大致步骤如下:
- 通过vm(Java虚拟机)参数获取JNIEnv变量
- 通过FindClass方法找到对应的Java类
- 通过RegisterNatives方法,传入JNINativeMethod数组,注册native函数
方法签名
- (参数类型标识1参数类型标识2...参数类型标识n)返回值类型标识
类型标识对应关系如下:
| 类型标识 | Java类型 |
| Z | boolean |
| B | byte |
| C | char |
| S | short |
| I | int |
| J | long |
| F | float |
| D | double |
| L包名/类名; | 各种引用类型 |
| V | void |
另外,当Java类型为数组时,在标识前会有“[”符号,例如:String[] 类型标识为 [Ljava/lang/String;
- // Signature: ()V
- public native void f();
- // Signature: (ID)I
- public native int f(int a, double b);
- // Signature: (Ljava/lang/Object;Ljava/lang/String;)V
- public native void f(Object a, String b);
- // Signature: ()V
- public native void g();
- BufferedReader使用readLine问题
有时我们在使用BufferedReader时候会发现使用readLine函数迟迟没有任何返回,这是因为BufferedReader和BufferedWriter是基于行进行操作的,因此我们使用BufferedWriter的时候使用newLine函数即可,具体代码如下:
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
- writer.write(str);
- writer.newLine();
- writer.flush();
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- str = reader.readLine();
JNI 方法注册与签名+BufferedReader使用readLine问题的更多相关文章
- Dalvik虚拟机JNI方法的注册过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8923483 在前面一文中,我们分析了Dalvi ...
- JNI 函数注册与管理
class<--> 一一对应so-->method 每个so对应于一个类对象 类中的每个native方法对应 于so中的一个native的function,对应关系涉及 {c ...
- Android Studio NDK JNI动态注册本地方法
概述 可能大家觉得javah生成的函数名又臭又长,不太好看.这里可以提供另外一种方法来动态注册c++函数,让其根Java中的native方法关联起来. 实现 这里通过JNIEnv的Resisterna ...
- Java Native Interface 五 JNI里的多线程与JNI方法的注册
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 JNI里的多线程 在本地方法里写有关多线程的 ...
- Android有关JNI 学习(两)为JNI方法名称,数据类型和方法签名的一些知识
我们知道,使用javah产生c/c++当在头文件,将java定义 native 功能,以产生相应jni层功能,如下面: /* * Class: com_lms_jni_JniTest * Method ...
- JNI动态注册native方法及JNI数据使用
前言 或许你知道了jni的简单调用,其实不算什么百度谷歌一大把,虽然这些jni绝大多数情况下都不会让我们安卓工程师来弄,毕竟还是有点难,但是我们还是得打破砂锅知道为什么这样干吧,至少也让我们知道调用流 ...
- Java中使用BufferedReader的readLine()方法和read()方法来读取文件内容
目标:读文件 编程时,有很多时候需要读取本地文件,下面介绍一下读取方式: 读单行文件 package com; import java.io.*; import java.util.ArrayList ...
- JNI的第2种写法:本地方法注册
声明:迁移自本人CSDN博客https://blog.csdn.net/u013365635 孔乙己说,茴香豆的茴有四种写法,今天谈谈JNI的第2种写法:本地方法注册. 这种写法的好处是不需要使用ja ...
- 技术转载:Jni学习四:如何编写jni方法
转载:http://blog.chinaunix.net/u1/38994/showart_1099528.html 一.概述: 在这篇文章中将会简单介绍如何编制一些简单的JNI 方法.我们都知道JN ...
随机推荐
- istio入门(02)istio的架构和概念
Istio从逻辑上可以分为数据平面和控制平面: 数据平面主要由一系列的智能代理(Envoy)组成,管理微服务之间的网络通信 控制平面负责管理和配置这些智能代理,并动态执行策略 主要由以下组件构成 En ...
- Docker学习实践 - Docker安装MySql数据库
Docker安装MySQL数据库 1.Ubuntu安装MySQL安装 (1)安装编译源码需要的包 sudo apt-get install make cmake gcc g++ bison libnc ...
- JSON(一)——JSON与JavaScript的关系
JSON是一种轻量级的数据交换格式,全称--JavaScript 对象表示法(JavaScript Object Notation). 类比XML,你可以把JSON看作是一种存储数据的格式类型,一种数 ...
- loadrunner录制时web时,安全证书问题
测试环境:win7+LoadRunner11+ie9 遇到的问题:用LoadRunner录制时,打开百度,总是报安全证书问题,如图所示 解决方法:Tools——Recording Options——p ...
- jedis配置
public interface IJedisClientFactory { Jedis getJedis(); } JedisClientFactoryImpl.java @Service publ ...
- Centos下安装 .net Core运行程序
首先要进行更新下镜像文件 sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc sudo sh -c 'echo -e ...
- Spring(4)——面向切面编程(AOP模块)
Spring AOP 简介 如果说 IoC 是 Spring 的核心,那么面向切面编程就是 Spring 最为重要的功能之一了,在数据库事务中切面编程被广泛使用. AOP 即 Aspect Orien ...
- Java集合框架知多少——干货!!!
Java集合框架的组成 注意:四个接口的区别 ① Collection:存储无序的.不唯一的数据: ② List:存储有序的.不唯一的数据: ③ Set:存储无序的.唯一的数据: ④ Map:以键值对 ...
- eclipse导包导不进来
今天某个类转移了位置,结果导包导不进来: 解决方法:1.查看本项目中pom的依赖关系,查看是否引用了转移后的项目. 2.查看导不进来的报错类,查看类刚开始import的信息,如果有报错,删除后重新导包 ...
- Python3玩转儿 机器学习(3)
机器学习算法可以分为: 监督学习 非监督学习 半监督学习 增强学习 监督学习:给机器的训练数据拥有"标记"或者"答案",例如: 我们需要告诉机器左边的画面是一只 ...