JNI开发笔记(一)

C/C++  互相通过的接口,本地的C/C++代码可以调用Java代码
JNI是本地编程接口,NDK快速开发C(C++)动态库,将so和Java应用一起打包成apk
将复杂的逻辑和算法通过本地代码(C/C++)

反汇编.so动态库分析程序的逻辑要复杂
设备提供C接口,而Java不能直接与C进行交互,先在Java层定义发送短信等 native方法,用javah命令将定义Java native接口的class字节码文件生成.h文件,最后用设备的C接口实现java的native方法,编译成 .dll或 .so动态库


打开一个网页,播放视频或打开窗口,C++实现麻烦,用Android应用层提供的API变得容易。Cocos2d-x封装
应用程序需要调用硬件的特定功能,只能通过C/C++封装的JNI接口来提供上层应用
厂商封装好JNI接口,了解JNI与Java通讯原理

C和C++ 复用以前用C/C++写的大量代码

JNI程序受系统环境影响,C/C++编译的模块或代码依赖系统提供的库函数和本地库,不同的操作系统,有自己的本地库和CPU指令集,各个平台的C/C++规范和标准库函数实现方式也有所区别

1.编写声明native方法的Java类
2.Java源代码编程成class字节码文件
3.用javah -jni 生成 .h头文件  -jni表示将class中用native声明的函数
4.用本地代码实现 .h 文件中的函数
5.本地代码编译成动态库 Windows:*.dll Linux:*.so Mac OSx:*.jnilib
6.拷贝动态库至 java.library.path 本地库搜索目录下,运行Java程序

HelloWorld.java

public class HelloWord{
	public calss HelloWorld{
		public static native String sayHello(String name);
		
		public static void main(String[] args){
			String tet = sayHello("yang");
			System.out.println(text);
		}
	}
	
	staic{
		System.loadLibrary("HelloWorld");
	}
}

用本地代码实现 .h 文件中的函数
将C/C++代码编译成本地动态库文件,libHelloWorld.so

一般在类的静态代码块中加载动态库最合适
方式1:只需要动态库名字,不需要lib前缀,也不要.so, .dll, .jnilib后缀
System.loadLibrary("HelloWorld");  java会去java.library.path系统指定目录
方式2:指定动态库的绝对路径,需要前缀后缀
System.load("/User/yangxin/Desktop/libHelloWorld.jnilib");

javah -classpath ./bin//classpath 类搜索路径

javac src/com/HelloWorld.java -d ./bin
-d 表示编译后的class文件放在指定目录下,放在src同级的bin目录

没有将动态库拷贝到本地搜索目录下,执行 java 命令,添加系统属性 java.library.path指定动态库目录  java -Djava.library.path=/Users/yangxin/Desktop
指定系统属性,Linux环境下可设置 LD_LIBRARY_PATH 环境变量指定库的搜索目录

gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared
-I      包含编译JNI必要的头文件
-fPIC   编译成位置无关独立代码
-shared 编译成到动态库
-o      编译后动态库生成的路径和文件名

JNIEXPORT jstring JNICALL Java_com_study_jnilearn_HelloWorld_sayHello
(JNIEnv *, jclass, jstring)
{
	const char *c_str = NULL;
	char buff[128] = {0};
	c_str = (*env)->GetStringUTFChars(env, j_str, NULL);
	if(c_str == NULL){
		printf();
		return NULL;
	}
	(*env)->ReleaseStringUTFChars(env, j_str, c_str);
	printf("Java Str:%s\n", c_str);
	sprintf(buff, "hello %s", c_str);
	return (*env)->NewStringUTF(env, buff);
}
JVM查找native方法
   调用System.loadLibrary接口 加载实现了native方法的动态库才能正常访问
JVM查找native方法
  按照JNI规范的命名法则
  调用JNI提供的 RegisterNatives 函数,注册到JVM


编译动态库时,用-I包含了两个头文件目录,一个jni.h头文件,一个跨平台头文件目录,用于定义与平台相关的宏,其中用于标识 JNIEXPORT JNICALL
在Windows中编译dll动态库规定,如果动态库中函数要被外部调用,在函数声明中添加 __declspec(dllexport)标识,在Linux/Unix这两个宏可以省略。由于各自的编译器所产生的可执行文件格式不一样。


javah工具生成函数原型的头文件命名规则: Java_类全路径_方法名
JNIEXPORT jstring JNICALL Java_com_study_jnilearn_HelloWorld_sayHello(JNIEnv *, jclass, jstring);
第一个参数:JNIEnv * 定义任意native函数的第一个参数(调用JNI的RegisterNatives函数注册的函数),指向JVM函数表的指针,函数表每一个入口指向一个JNI函数
第二个参数:Java中调用 native 方法的实例或Class对象,如果这个native方法是实例方法,则参数是 jobject,如果是静态方法,则是 jclass
第三个参数:Java对应JNI中的数据类型,Java中String类型对应JNI中的jstring


熟悉命名规则后,不通过javah生成相应的java native方法的函数原型,只需要按照命名规则编写相应的函数原型和实现。
com.study.jni.Utils   计算加法native的add
public native int add(int, int);
JNIEXPORT jint JNICALL Java_com_study_jni_Utils_add(JNIEnv *, jobject, jint,jint);
Java层函数名如果有一个"_",转换成JNI后变成了"_l"
JNIEXPORT void JNICALL Java_android_media_MediaScanner_native_linit
JNIEXPORT void JNICALL Java_android_media_MedaiScanner_processFile


基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值