Hotspot JNI调用详解

目录

一、HelloWorld

1、javah命令

2、动态链接库

3、实现JNI接口

4、生成动态链接库

5、System.load

6、JNIEnv RegisterNatives

二、JDK库文件

1、位置

2、源代码

三、本地方法的字节码


     上一篇博客《Hotspot 类加载、链接和初始化 C++源码解析》中讲到了ClassLoader类加载的4个本地方法,那么为啥要使用本地方法?本地方法跟普通的Java方法有啥区别?本地方法又称JNI(Java Native Interface)调用,即通过java方法调用使用本地代码如C/C++实现的方法,通过本地方法Java可以获取底层操作系统提供的能力,如文件读写,网络I/O,利用GPU计算等,可以借助其他语言实现Java本身并不直接支持的特性,如利用C/C++的开源库来实现Java的协程,可以借助底层语言如汇编实现对性能要求较高的功能,除此之外还可以通过本地方法与JVM本身,任一Java对象交互,如ClassLoader中通过启动类加载器加载核心类库,JVM的监控等。本地方法在以数据加工处理的后端应用中比较少见,但是在需要经常跟底层硬件交互的Android中经常使用。

一、HelloWorld

     JNI接口又称本地方法,在Java代码中JNI接口通过native关键字标识,接口定义完后使用javah命令生成头文件,然后使用C/C++实现头文件中的方法,并将其编译成windows上ddl文件或者Linux上的so文件等动态链接库。测试用例如下:

package jni;


public class HelloWorld {

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

    public native static void say(String content);

    public static void main(String[] args) {
         HelloWorld.say("JNI native Hello World!");
    }
}

1、javah命令

     javah命令就是用来给JNI接口生成符合JNI调用规范的头文件的,在命令行执行javah -h可查看其使用帮助,如下:

为了避免通过选项指定查找路径和输出路径,可进入到包含目标class文件的目录下执行javah命令, 如图中的test-classes目录,因为javah默认在当前目录下查找目标class,并将结果头文件默认放到当前目录。执行javah -jni -v -o HelloWorld.h jni.HelloWorld生成头文件,如下图:

头文件的内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
//jni.h是JNI调用C++相关方法的头文件,由JVM定义
#include <jni.h>
/* Header for class jni_HelloWorld */

#ifndef _Included_jni_HelloWorld
#define _Included_jni_HelloWorld
//宏定义,表示如果是C++环境,即JNI调用默认是通过C实现的,C++环境需要通过extern C的方式
//告诉编译器这是一段C代码
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jni_HelloWorld
 * Method:    say
 * Signature: (Ljava/lang/String;)V
 */
//JNIEXPORT和JNICALL都是宏定义
JNIEXPORT void JNICALL Java_jni_HelloWorld_say
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

其中jni.h及其包含的其他头文件可以在JAVA_HOME\include目录下找到,如下图:

JNIEXPORT和JNICALL的宏定义位于jni_md.h中,该头文件通过jni.h引入的,如下:

 __attribute__是GCC编译器使用的,这个宏定义是向编译器表示该方法的可见性的,这里不做详细讨论。

2、动态链接库

    参考 《 编译过程和ELF文件》,动态链接库是运行期按需加载链接的共享函数库,在Linux上典型的如实现C标准函数库的glibc对应的动态链接库文件为lib目录下的libc.so,在windows上就是dll后缀的文件,dll是Dynamic Link Library的缩写,通常位于C:\Windows\System32目录下。JVM依赖的动态链接库文件通常位于JAVA_HOME\jre\bin目录下,windows上的如下图:

应用程序可以从动态链接库中根据方法名查找对应方法的实现,对C/C++而言就是获取对应方法的指针,然后通过指针调用方法,如ClassLoader类的load_zip_library方法的实现,代码如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值