Fork me on GitHub

HelloWorld之Java调用C++(JNI)

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

posted @ 2023-02-07 11:54  伊甸一点  阅读(82)  评论(0编辑  收藏  举报