关于Java中JNI的调用以及线程方法的实现

首先我们知道Java中的线程类是Thread类,而我们知道启动线程采用的是start方法,而start方法中会调用到一个native的start0方法,而Java中的native方法是通过jni的方式去调用底层C(C++)程序.本篇博客模拟Java中的创建线程的整个过程.
首先我们要知道操作系统中创建线程的方法,在lInux中采用方法是pthread_create()方法

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

其中的四个参数分别表示的含义为:

参数名称参数定义参数解释
pthread_t *thread传出的参数,调用后返回的线程ID定义一个线程ID
const pthread_attr_t *attr线程属性,关于线程属性是linux的知识一般传NULL,保持默认属性
void (start_routine)(void *)线程的启动后的主体函数需要你定义一个函数,然后传函数名即可
void *arg主体函数的参数没有可以传null

接着我们继续看一下Java中的线程大概的执行方法

 public void test(){
        Thread thread=new Thread(){
            @Override
            public void run() {
                System.out.println("this is thread!");
            }
        };
        thread.start();
    }

根据代码可以分析得,一个线程启动需要调用到线程的start方法,而通过start方法会继续调用到一个native的start0方法,接着通过JNI调用到操作系统的pthread_create方法.
根据这个流程我们就可以模拟出自己的线程方法.
1.首先模拟一个Java调用native方法

public class MyThread {
    static{
        System.loadLibrary("TestMyThread");
    }
    public static void main(String[] args){
        MyThread myThread = new MyThread();
        myThread.start0();
    }
    private native void start0();
    
}

这里要说一下我们需要自己装载一下类库.然后将这个编写好的文件放入Linux 环境下.而具体放的路径可以随意,但是最好跟你的包路径相同,否则你执行是需要移动文件路径
在这里插入图片描述
2.我们就需要编译相关代码了,使用Javac 命令

javac xxx.java

此时会多出一个.class文件.
接着我们需要获取JNI文件,通过javac -h . 命令执行

Javac -h . xxx.java

此时文件中会多出一个.h文件,这个文件很重要,我们需要根据这个文件进行c程序的编写.打开这个文件我们可以看到一下内容:

#include <jni.h>
/* Header for class thread_MyThread */

#ifndef _Included_thread_MyThread
#define _Included_thread_MyThread
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     thread_MyThread
 * Method:    start0
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_thread_MyThread_start0
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

我们需要将方法名复制一下,我们编写相关C语言代码需要用到.
3.编写C语言代码
接着我们就可以编写我们的C语言代码了,具体代码如下

#include <pthread.h>
#include <stdio.h>
#include <jni.h>
//定义变量接收线程id
pthread_t pid;
//线程的主主体方法, 相当于Java中的run
void * thread_entity(){
	while(1){
	   //睡眠100毫秒
	   usleep(100);
	  //打印
	  printf("I am new Thread \n ");
	}	
}

Java_thread_MyThread_start0(JNIEnv *evn, jobject c1){
	pthread_create(&pid,NULL,thread_entity,NULL);
	while(1){
	//睡眠100毫秒
	usleep(100);
	//打印
	printf(" I an main \n");
	}
}

这里有一个需要引入jni的库否则编译C语言编程SO文件时会报错.编写完后,我们继续将C文件上传至Linux环境上,你也可以在Linux上直接编写.文件最好上传到我们之前上传java文件的根包路径上.在这里插入图片描述
4.将C程序编译程SO程序
编译这个myThreadC.c为一个so文件,这样才能被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 libxxxll.so myThreadC.c

注:libxxx.so中的xxx是在Java代码中装载的库

static{
        System.loadLibrary("TestMyThread");
    }

此时文件下会多出一个.so文件,入图所示
在这里插入图片描述
5.添加环境变量
把so文件所在的目录添加到系统变量,不然java还是load不到

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/user/test

6.运行Java程序
最后我们运行Java文件即可以

Java xxx.xxx.MyThread

得到的结果如同所示:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值