6.Java JVM_2.java中native方法的使用

https://blog.csdn.net/flowingfirefly/article/details/7613869  Linux下测试Java的JNI(Java Native Interface)

/root/work目录下

1. 编写NativeTest.java, 代码如下:

public class NativeTest {
    /* 声明一个本地(native)函数 */
    public native static double max(double a, double b);
    static {
        /*
         * 关于loadLibrary的信息, 摘自 Java2 Platform SE 5 API:
         * public static void loadLibrary(String libname), 加载由libname参数指定的系统库。
         * 将库名映射到实际系统库的方法取决于系统。
         */
         System.loadLibrary("max");
    }
 
    public static void main(String[] args) {
        System.out.println(max(1.0, 2));
    }
}
2. 编译NativeTest.java, 并用javah生成该类对应的C/C++头文件:

javac NativeTest.java

javah NativeTest

执行上述命令后, 会在当前目录中生成一个名为 NativeTest.h 的头文件。

注 <为什么不是javah NativeTest.class> :

一定不能是javah NativeTest.class, 就像 运行NativeTest时一样,是java NativeTest 而不是java NativeTeset.class 。注 <javah> :

Q:javah是什么, 有什么作用?

A: javah是JDK里面的一个工具, 用来生成C/C++的头文件, 目的是为了让Java和C可以相互调用,以下是官方的描述, 摘自javah的man手册:

javah  produces C header files and C source files from a Java class.

These files provide the connective glue that allow your Java  and  C code to interact.

NativeTest.h 的内容如下

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

#ifndef _Included_NativeTest
#define _Included_NativeTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     NativeTest
 * Method:    max
 * Signature: (DD)D
 */
JNIEXPORT jdouble JNICALL Java_NativeTest_max
  (JNIEnv *, jclass, jdouble, jdouble);

#ifdef __cplusplus
}
#endif
#endif

3. 编译动态链接库,运行程序:

先写一个C源文件, 命名为 max.c , 代码如下:

#include "NativeTest.h"
 
/*
 * 这个函数的函数签名在NativeTest.h中有, 关于JNIEXPORT, jdouble, jni_env, class etc. 可以在 jni.h 中查看详细信息.
 * jni.h 一般在 $JAVA_HOME/include中, 实在找不到, 就 sudo find / -name "jni.h"
*/
 
 JNIEXPORT jdouble JNICALL Java_NativeTest_max
        (JNIEnv * jni_env, jclass class, jdouble a, jdouble b)
{
        return a > b? a: b;
}

接着, 就是编译动态链接库, 在编译之前, 必须配置好两个环境变量:LD_LIBRARY_PATH和 C_INCLUDE_PATH。

通过命令[ find / -name 'jni.h' ] + [ find / -name 'jni_md.h' ] + [ find / -name 'jawt_md.h'] 找到jni的头文件目录

/usr/java/jdk1.6.0_45/include/jni.h

/usr/java/jdk1.6.0_45/include/linux/jni_md.h

/usr/java/jdk1.6.0_45/include/linux/jawt_md.h

直接设置环境变量:LD_LIBRARY_PATH和 C_INCLUDE_PATH:

export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/java/jdk1.6.0_45/include 

export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/openjdk-debug/j2sdk-image/include/linux

export LD_LIBRARY_PATH=$LIBRARY_PATH:.

注 <怎么间接配置环境变量LD_LIBRARY_PATH和C_INCLUDE_PATH> :

export C_INCLUDE_PATH=$C_INCLUDE_PATH:$JAVA_HOME/include

export C_INCLUDE_PATH=$C_INCLUDE_PATH:$JAVA_HOME/include/linux

export LD_LIBRARY_PATH=$LIBRARY_PATH:.

注 <环境变量分隔符> :

Linux下的环境变量分隔符是冒号(:), Windows下是分号(;)。

配置好上述的环境变量后, 执行以下的命令编译动态链接库:

gcc max.c -fPIC -shared -o libmax.so

执行这个命令后, 当前目录中会生成一个名为libmax.so的文件。

注 <-fPIC,-shared,-o> :

-fPIC或-fpic是file position independent relocate 的缩写, 大致意思是位置无关并且可重定位。

-shared 指定了生成的库是共享库。

-o 指定输出

注 <生成的动态链接库为什么是 libmax.so 而不是别的> :

生成的库名一定为 lib*.so , 因为Linux系统下就是这么约定的, 还记不记得, 在上面的 NativeTest.java里,

有 System.loadLibrary("max") 的注释中, 有这样一句话: 加载由 libname 参数指定的系统库。

将库名映射到实际系统库的方法取决于系统。 在Linux下, 若库文件为 libmax.so, 则该库在系统中的库名为 max

最后,java NativeTest, 输出如下:

2.0

//======================================================================================//

https://www.cnblogs.com/yxysuanfa/p/7253560.html  java中native方法的使用

在非常多情况下,java须要调用其它语言的代码,比方c的代码。那么这个时候java中native方法就发挥作用了。以下就介绍native方法的使用。

一、JNI使用流程

     a.编写带有native声明的方法的Java类

    b.使用javac命令编译编写的Java类

    c.使用java -jni ****来生成后缀名为.h的头文件

    d.使用其它语言(C、C++)实现本地方法

    e.将本地方法编写的文件生成动态链接库

二、实践

1、编写类代码 /root/work目录下创建 com/sunny/demo/ 目录,同时创建com/sunny/demo/Demo01.java文件。

package com.sunny.demo;

public class Demo01 {
        public native void hello();//没有实现

        static{
             System.loadLibrary("hello");//在类载入的 时候载入dll
          }

        public static void main(String[] args){

            new Demo01().hello();
         }

}

2、编译 /root/work目录执行编译

javac com/sunny/demo/Demo01.java(注意,我这里是带包编译)

生成 com/sunny/demo/Demo01.class

3、生成.h文件  /root/work目录执行jni

javah -jni com.sunny.demo.Demo01(注意。头文件生成文件夹的位置。不知.java文件的位置,而在和包同级文件夹中,这里生成的文件名称为com_sunny_demo_Demo01.h)

生成 com_sunny_demo_Demo01.h

4、用c实现hello方法

(1)当中com_sunny_demo_Demo01.h中代码例如以下(javah自己主动生成的)

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

#ifndef _Included_com_sunny_demo_Demo01
#define _Included_com_sunny_demo_Demo01
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_sunny_demo_Demo01
 * Method:    hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_sunny_demo_Demo01_hello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

(2)创建com_sunny_demo_Demo01.c文件,实现hello方法

#include<stdio.h>
#include"com_sunny_demo_Demo01.h"
JNIEXPORT void JNICALL Java_com_sunny_demo_Demo01_hello(JNIEnv * a, jobject b){
	printf("hello world");
}

(3)用linux生成动态链接库

3.1 通过命令[ find / -name 'jni.h' ] + [ find / -name 'jni_md.h' ] + [ find / -name 'jawt_md.h'] 找到jni的头文件目录

/usr/java/jdk1.6.0_45/include/jni.h

/usr/java/jdk1.6.0_45/include/linux/jni_md.h

/usr/java/jdk1.6.0_45/include/linux/jawt_md.h

3.2 设置环境变量:LD_LIBRARY_PATH和 C_INCLUDE_PATH:

export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/java/jdk1.6.0_45/include 

export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/openjdk-debug/j2sdk-image/include/linux

export LD_LIBRARY_PATH=$LIBRARY_PATH:.

3.3. 编译 /root/work/目录下执行

gcc com_sunny_demo_Demo01.c -fPIC -shared -o libhello.so

说明:编译时假设产生例如以下错误:fatal error C1083: Cannot open include file: 'jni.h': No such file or directory。说明没有找到jni.h。到jdk的安装文件夹 include/jni.h;include/linux/jni_md.h;include/linux/jawt_md.h这3个文件复制到vc的安装文件夹include中

5.执行java com.sunny.demo.Demo01就会出现例如以下结果

java com/sunny/demo/Demo01  or java com.sunny.demo.Demo01

hello world

三、总结:

上面的样例中,我是带包编译的,所以文件存放和生成的位置一定要注意,在java层面我们仅仅须要dll文件,.h和.cd 文件的目的仅仅是为了生成dll文件.最后给出我代码的文件夹结果

.h文件是javah生成的,dll文件是应该放的位置(假设不放在这个位置。执行报错,找不到hello这个库)

dll參考文章:http://www.cnblogs.com/chio/archive/2007/11/03/948480.html

external c :http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html

java native文章: http://blog.163.com/yueyemaitian@126/blog/static/21475796200701491621267

猜你喜欢

转载自blog.csdn.net/qq_20398345/article/details/81626609
今日推荐