JNI示例

Linux下,没有在Andorid下面搞,安卓开发效率太低了。。只是单纯手搓一下。。

HelloJNI.java

public class HelloJNI {
    static {
        System.loadLibrary("hello"); // 加载本地库
    }

    // 声明一个本地方法
    private native void sayHello();

    public static void main(String[] args) {
        new HelloJNI().sayHello(); // 调用本地方法
    }
}

hello.cpp

#include <jni.h>
#include <iostream>

// 定义本地方法
extern "C" JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *, jobject) {
    std::cout << "Hello from C++!" << std::endl;
}

生成JNI头文件

javac HelloJNI.java
javah -jni HelloJNI

这里会生成HelloJNI.class。

之后会生成头文件,HelloJNI.h。

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

#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloJNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloJNI_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

中间可能会提示Java没有装,装下面几个就可以了。也不用全装,headless装一个就行了。

sudo apt install openjdk-11-jdk-headless  # version 11.0.23+9-1ubuntu1~20.04.2, or
sudo apt install default-jdk              # version 2:1.11-72
sudo apt install openjdk-13-jdk-headless  # version 13.0.7+5-0ubuntu1~20.04
sudo apt install openjdk-16-jdk-headless  # version 16.0.1+9-1~20.04
sudo apt install openjdk-17-jdk-headless  # version 17.0.11+9-1~20.04.2
sudo apt install openjdk-21-jdk-headless  # version 21.0.3+9-1ubuntu1~20.04.1
sudo apt install openjdk-8-jdk-headless   # version 8u412-ga-1~20.04.1
sudo apt install ecj                      # version 3.16.0-1

编译和运行

export JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-amd64"
g++ -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -shared -o libhello.so hello.cpp
java -Djava.library.path=. HelloJNI

之后就会生成libhello.so

然后直接运行即可。

其实可以看到,JNI整个也并没有做太多东西,本质就是一个动态运行库。整个也没有对操作系统,语言做一些很深层次的定制,大部分还是基于语言的特性来弄的。有空可以看看JNI那几个宏,就一切都明白了。

#define JNIEXPORT  __attribute__ ((visibility ("default")))

。。。

对了,这个so本身也是ELF格式的,可以用相关命令查看。

ubuntu@VM-8-10-ubuntu:~/test/jni$ readelf -h libhello.so
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x10c0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          14944 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         11
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

详细看可以看到里面有两个符号表,常规的.symtab, 另一种是精简的.dynsym。要链接的是在动态中,也就是12: 0000000000001179    66 FUNC    GLOBAL DEFAULT   14 Java_HelloJNI_sayHello

只要代码里面稍微改变一点,就可以看到这个函数大小发生变化。

ubuntu@VM-8-10-ubuntu:~/test/jni$ readelf -s libhello.so

Symbol table '.dynsym' contains 13 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4 (2)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@GLIBC_2.2.5 (3)
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4 (2)
     5: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZStlsISt11char_traitsIcE@GLIBCXX_3.4 (2)
     7: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
     8: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (3)
     9: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND _ZSt4cout@GLIBCXX_3.4 (2)
    10: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSolsEPFRSoS_E@GLIBCXX_3.4 (2)
    11: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZSt4endlIcSt11char_trait@GLIBCXX_3.4 (2)
    12: 0000000000001179    66 FUNC    GLOBAL DEFAULT   14 Java_HelloJNI_sayHello

Symbol table '.symtab' contains 62 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000000002a8     0 SECTION LOCAL  DEFAULT    1
     2: 00000000000002c8     0 SECTION LOCAL  DEFAULT    2
     3: 00000000000002f0     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000318     0 SECTION LOCAL  DEFAULT    4
     5: 0000000000000450     0 SECTION LOCAL  DEFAULT    5
     6: 00000000000005b8     0 SECTION LOCAL  DEFAULT    6
     7: 00000000000005d8     0 SECTION LOCAL  DEFAULT    7
     8: 0000000000000618     0 SECTION LOCAL  DEFAULT    8
     9: 0000000000000720     0 SECTION LOCAL  DEFAULT    9
    10: 0000000000001000     0 SECTION LOCAL  DEFAULT   10
    11: 0000000000001020     0 SECTION LOCAL  DEFAULT   11
    12: 0000000000001070     0 SECTION LOCAL  DEFAULT   12
    13: 0000000000001080     0 SECTION LOCAL  DEFAULT   13
    14: 00000000000010c0     0 SECTION LOCAL  DEFAULT   14
    15: 0000000000001224     0 SECTION LOCAL  DEFAULT   15
    16: 0000000000002000     0 SECTION LOCAL  DEFAULT   16
    17: 0000000000002014     0 SECTION LOCAL  DEFAULT   17
    18: 0000000000002050     0 SECTION LOCAL  DEFAULT   18
    19: 0000000000003de0     0 SECTION LOCAL  DEFAULT   19
    20: 0000000000003df0     0 SECTION LOCAL  DEFAULT   20
    21: 0000000000003df8     0 SECTION LOCAL  DEFAULT   21
    22: 0000000000003fc8     0 SECTION LOCAL  DEFAULT   22
    23: 0000000000004000     0 SECTION LOCAL  DEFAULT   23
    24: 0000000000004038     0 SECTION LOCAL  DEFAULT   24
    25: 0000000000004040     0 SECTION LOCAL  DEFAULT   25
    26: 0000000000000000     0 SECTION LOCAL  DEFAULT   26
    27: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    28: 00000000000010c0     0 FUNC    LOCAL  DEFAULT   14 deregister_tm_clones
    29: 00000000000010f0     0 FUNC    LOCAL  DEFAULT   14 register_tm_clones
    30: 0000000000001130     0 FUNC    LOCAL  DEFAULT   14 __do_global_dtors_aux
    31: 0000000000004040     1 OBJECT  LOCAL  DEFAULT   25 completed.8061
    32: 0000000000003df0     0 OBJECT  LOCAL  DEFAULT   20 __do_global_dtors_aux_fin
    33: 0000000000001170     0 FUNC    LOCAL  DEFAULT   14 frame_dummy
    34: 0000000000003de0     0 OBJECT  LOCAL  DEFAULT   19 __frame_dummy_init_array_
    35: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.cpp
    36: 0000000000002000     1 OBJECT  LOCAL  DEFAULT   16 _ZStL19piecewise_construc
    37: 0000000000004041     1 OBJECT  LOCAL  DEFAULT   25 _ZStL8__ioinit
    38: 00000000000011bb    77 FUNC    LOCAL  DEFAULT   14 _Z41__static_initializati
    39: 0000000000001208    25 FUNC    LOCAL  DEFAULT   14 _GLOBAL__sub_I_hello.cpp
    40: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    41: 0000000000002120     0 OBJECT  LOCAL  DEFAULT   18 __FRAME_END__
    42: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS
    43: 0000000000002014     0 NOTYPE  LOCAL  DEFAULT   17 __GNU_EH_FRAME_HDR
    44: 0000000000001224     0 FUNC    LOCAL  DEFAULT   15 _fini
    45: 0000000000004000     0 OBJECT  LOCAL  DEFAULT   23 _GLOBAL_OFFSET_TABLE_
    46: 0000000000004040     0 OBJECT  LOCAL  DEFAULT   24 __TMC_END__
    47: 0000000000004038     0 OBJECT  LOCAL  DEFAULT   24 __dso_handle
    48: 0000000000003df8     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC
    49: 0000000000001000     0 FUNC    LOCAL  DEFAULT   10 _init
    50: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    51: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitC1Ev@@
    52: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@@GLIBC_2.2.5
    53: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitD1Ev@@
    54: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab
    55: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZStlsISt11char_traitsIcE
    56: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    57: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@@GLIBC_2.2
    58: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND _ZSt4cout@@GLIBCXX_3.4
    59: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSolsEPFRSoS_E@@GLIBCXX
    60: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZSt4endlIcSt11char_trait
    61: 0000000000001179    66 FUNC    GLOBAL DEFAULT   14 Java_HelloJNI_sayHello

当然,用nm也可以查看:

ubuntu@VM-8-10-ubuntu:~/test/jni$ nm libhello.so
0000000000004040 b completed.8061
                 U __cxa_atexit@@GLIBC_2.2.5
                 w __cxa_finalize@@GLIBC_2.2.5
00000000000010c0 t deregister_tm_clones
0000000000001130 t __do_global_dtors_aux
0000000000003df0 d __do_global_dtors_aux_fini_array_entry
0000000000004038 d __dso_handle
0000000000003df8 d _DYNAMIC
00000000000012d0 t _fini
0000000000001170 t frame_dummy
0000000000003de0 d __frame_dummy_init_array_entry
0000000000002120 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
00000000000012b4 t _GLOBAL__sub_I_hello.cpp
                 w __gmon_start__
0000000000002014 r __GNU_EH_FRAME_HDR
0000000000001000 t _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000001179 T Java_HelloJNI_sayHello
00000000000010f0 t register_tm_clones
0000000000004040 d __TMC_END__
0000000000001267 t _Z41__static_initialization_and_destruction_0ii
                 U _ZNSolsEPFRSoS_E@@GLIBCXX_3.4
                 U _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
                 U _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
                 U _ZSt4cout@@GLIBCXX_3.4
                 U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@@GLIBCXX_3.4
0000000000002000 r _ZStL19piecewise_construct
0000000000004041 b _ZStL8__ioinit
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@@GLIBCXX_3.4

还是一个分析工具就是objdump,空了再单独写一个ELF吧。

参考:

https://www.cnblogs.com/computer1-2-3/p/15879165.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值