JNI的作用简单来说就是通过把c文件生成一个动态链接,然后用java的方法调用c函数。在此时在liunx系统下进行的操作。
1.装载库,保证JVM在启动的时候就会装载,故而一般是也给static
public class Demo{
static {
System.loadLibrary( "HelloNative" );
}
public static void main(String[] args) {
sun();
}
public static native void sun();
}
2.编译成class文件
在linux系统下把java文件编译成class文件。
javac xxx
3.生成.h头文件
javah 包名+类名
生成的.h文件需要放到包当中
3.编写C文件
c文件的方法需要参考.h文件里一个方法
现在假设.h文件如下所示
那么重要的是方框内的函数,那么c文件就得如下所写,这里的方法写的是通信服务器,但不是重点。
#include<stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "com_ServerLuban.h"
JNIEXPORT void JNICALL Java_com_ServerLuban_conn(JNIEnv *env, jobject c1){
int lfd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET; // ipv4
my_addr.sin_port = htons(8080);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);//
bind(lfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
listen(lfd, 128);
printf("listen client @port=%d...\n",8080);
struct sockaddr_in client_addr;
char cli_ip[INET_ADDRSTRLEN] = "";
socklen_t cliaddr_len = sizeof(client_addr);
int connfd = 0;
connfd = accept(lfd, (struct sockaddr*)&client_addr, &cliaddr_len);
inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);
printf("----------------------------------------------\n");
printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));
char recv_buf[512] = "";
while(1)
{
int k =read(connfd,recv_buf,sizeof(recv_buf));
printf("recv data=%d\n",k);
printf("%s\n",recv_buf);
}
close(connfd);
printf("client closed!\n");
close(lfd);
}
int main(){
return 0;
}
注意的就是c文件一个.h文件的引入和方法名必须和.h文件一致,其中方法里的参数是死的,记住就行”NIEnv *env, jobject c1“。
4.编译一个动态链接库
把c文件编译成一个动态链接库,这样java才能调用,指令如下
gcc -fPIC -I /usr/lib/jvm/java-1.8.0-openjdk/include -I /usr/lib/jvm/java-1.8.0-openjdk/include/linux -shared -o liblubanNet.so server.c
其中-o是指的编译后输出的文件名,前缀lib和后缀.so是不能变的
5.最后就是把这个库所在的目录添加到path
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxxxx
6.运行java
就可以通过java将c文件的方法执行出来。