JNI(Java Native Interface),通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。
JNI技术博客:https://blog.csdn.net/m0_37537867/article/details/124137225
1、java新建类HelloWorld,并声明native方法,引入hello的dll
public class HelloWorld { public native void hello(); static{ System.loadLibrary("hello"); } public static void main(String[] args){ new HelloWorld().hello(); } }
2、编译生成.class文件
javap HelloWorld.java
3、使用javah生成.h头文件,【生成的HelloWorld.h 不要做任何修改】
javah HelloWorld
文件明细如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: HelloWorld * Method: hello * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloWorld_hello (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
4、使用C或C++实现hello()方法
#include "jni.h" #include "HelloWorld.h" #include <stdio.h> JNIEXPORT void JNICALL Java_HelloWorld_hello(JNIEnv *env,jobject obj){ printf("Hello World!\n"); return; }
5、将jni_md.h文件拷贝到include文件夹下
sudo cp /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/include/darwin/jni_md.h /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/include
6、将.c文件编译并生成动态链接库
其中:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/include
替换为本地的jdk路径中的include文件路径
gcc -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/include HelloWorldImpl.c -o libhello.jnilib
gcc -dynamiclib -I 这里是include路径 HelloWorldImpl.c -o libhello.jnilib
生成的动态链接库,libhello.jnilib 对应 java代码中的 hello,这里映射大小写不敏感
也就是libhello.jnilib 可以映射到 HELLO、hello、Hello、HellO等
也就是libHELLO.jnilib 可以映射到 HELLO、hello、Hello、HellO等
7、查看当前目录文件信息
8、运行java的main方法
java HelloWorld
9、查看HelloWorld的字节码
javap -c -v HelloWorld.class > HelloWorld.txt
字节码如下所示:
Classfile /Users/pfzheng/Downloads/demo/HelloWorld.class Last modified 2023-2-7; size 442 bytes MD5 checksum 21235e46a38830416fd799866dd7b048 Compiled from "HelloWorld.java" public class HelloWorld minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #7.#18 // java/lang/Object."<init>":()V #2 = Class #19 // HelloWorld #3 = Methodref #2.#18 // HelloWorld."<init>":()V #4 = Methodref #2.#20 // HelloWorld.hello:()V #5 = String #12 // hello #6 = Methodref #21.#22 // java/lang/System.loadLibrary:(Ljava/lang/String;)V #7 = Class #23 // java/lang/Object #8 = Utf8 <init> #9 = Utf8 ()V #10 = Utf8 Code #11 = Utf8 LineNumberTable #12 = Utf8 hello #13 = Utf8 main #14 = Utf8 ([Ljava/lang/String;)V #15 = Utf8 <clinit> #16 = Utf8 SourceFile #17 = Utf8 HelloWorld.java #18 = NameAndType #8:#9 // "<init>":()V #19 = Utf8 HelloWorld #20 = NameAndType #12:#9 // hello:()V #21 = Class #24 // java/lang/System #22 = NameAndType #25:#26 // loadLibrary:(Ljava/lang/String;)V #23 = Utf8 java/lang/Object #24 = Utf8 java/lang/System #25 = Utf8 loadLibrary #26 = Utf8 (Ljava/lang/String;)V { public HelloWorld(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 6: 0 public native void hello(); descriptor: ()V flags: ACC_PUBLIC, ACC_NATIVE public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: new #2 // class HelloWorld 3: dup 4: invokespecial #3 // Method "<init>":()V 7: invokevirtual #4 // Method hello:()V 10: return LineNumberTable: line 15: 0 line 16: 10 static {}; descriptor: ()V flags: ACC_STATIC Code: stack=1, locals=0, args_size=0 0: ldc #5 // String hello 2: invokestatic #6 // Method java/lang/System.loadLibrary:(Ljava/lang/String;)V 5: return LineNumberTable: line 10: 0 line 11: 5 }
SourceFile: "HelloWorld.java"
在上述字节码中可以看到hello()方法,被标识为ACC_NATIVE
10、安装IDEA插件jclasslib 查看字节码
插件主页:https://plugins.jetbrains.com/plugin/9248-jclasslib-bytecode-viewer
安装成功后,在View -> Show Bytecode with jclasslib