基础储备----Java本地方法


1. 前言

之前在公司开发的时候, 需要用到内部的组件, 尽管提供了jar包, 但是jar包底层是通过Java本地方法实现的, 所以仅仅导入jar包并不能正常使用, 还需要安装内部组件的环境. 所以写这篇文章记录Java本地方法的使用, 帮助自己熟悉这块的使用.

2. 基础使用

基于Linux环境, 这个章节简单介绍如何实现一个Java本地方法.

第一步: 建立一个普通的java类, 添加一个方法, 在方法返回值前加 native

public class ClassMethod {
    //本地方法可以是静态的也可以是非静态的;
    public static native void greeting();
}

第二步: 编译这个java类, 得到ClassMethod.class文件

javac ClassMethod.java 

第三步: 找到当前类编译的.class文件, 使用命令行生成.h文件

javah ClassMethod

第四步: 查看ClassMethod.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class ClassMethod */

#ifndef _Included_ClassMethod
#define _Included_ClassMethod
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     ClassMethod
 * Method:    greeting
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_ClassMethod_greeting
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

第五步: 新建cpp文件, 并写逻辑代码(我这边命名为main.cpp,其实是可以随意命名的)

#include "ClassMethod.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_ClassMethod_greeting(JNIEnv *, jclass){
    printf("hello world!");
}

第六步: 将main.cpp文件和ClassMethod.h放到一个目录下, 并执行指令生成动态链接库.so文件

gcc -fPIC -I /home/ganlu/java/jdk1.8.0_144/include/ -I /home/ganlu/java/jdk1.8.0_144/include/linux/ -shared -o libHello.so main.cpp 

第七步: 将动态链接库复制到java项目中

public class ClassMethod {
    static
    {
        System.load("/home/ganlu/java/workplace/libHello.so");
    }
    //本地方法可以是静态的也可以是非静态的;
    public static native void greeting();

    public static void main(String args[]){
    greeting();
    }
}

第八步: 重新编译ClassMethod.java并执行

javac ClassMethod.java
java ClassMethod

运行结果:

hello world!

Java本地方法

3. 几个问题

3.1 动态链接库

我这边动态链接库的加载是通过绝对路径的指定来实现的, 而实际中, 这种绝对路径的指定肯定是不好的.

System.load("/home/ganlu/java/workplace/libHello.so");

网上流传比较多的一种做法是如下(这里要注意, .so文件的命名一定要规范, 以lib开头, 以.so结尾):

System.loadLibrary("Hello");

但是用这种方法直接运行, 会报错.

Exception in thread "main" java.lang.UnsatisfiedLinkError: no Hello in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at ClassMethod.<clinit>(ClassMethod.java:4)

3.1.1 解决方法一:通过Java运行参数指定java.library.path

java -Djava.library.path=. ClassMethod 

3.1.2 解决方法二:通过配置 LD_LIBRARY_PATH 环境变量

sudo gedit /etc/profile

export LD_LIBRARY_PATH=/home/ganlu/java/workplace

3.2 工作流程图

工作流程图

3.3 常见异常

如果出现以下异常, 则说明.so文件不对, 是因为java 程序在调用.so时候, 不能找到native method 方法的实现.
主要是因为在.so中, 可能xxx.h头文件中的接口名和xxx.cpp源文件中的实现函数名不一致导致的.

Exception in thread "main" java.lang.UnsatisfiedLinkError: test.ClassMethod.greeting()V
    at test.ClassMethod.greeting(Native Method)
    at test.ClassMethod.main(ClassMethod.java:11)

4. 参考链接

https://blog.csdn.net/qq_31105311/article/details/51255479
https://www.cnblogs.com/zh1164/p/6283831.html
https://blog.csdn.net/missingu1314/article/details/12650725

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值