Android开发实践:JNI函数签名生成器

本文介绍了一个用于Android NDK开发的JNI签名生成工具类,通过该工具可以为Java Native方法生成唯一的签名字符串,以便在JNI环境中唯一标识这些方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    “函数签名”在Android NDK开发中很常见,由于Java支持重载,仅靠函数名无法唯一确定一个方法。因此,JNI提供了一套签名规则,用一个字符串来唯一确定一个Java端定义的Native方法。


     具体每一种Java数据类型对应的签名字符串如下所示(来自Oracle官网JNI的介绍):


    wKiom1SOxRfjmgaBAAHVKEL-bG0476.jpg


    原理其实并不复杂,每种基本类型对应一个单字符签名,而类则对应为"L"+类的全路径+";",数组类型则对应"["+元素类型的签名,函数的签名则是:(各参数类型签名)+ 返回类型的签名。


    搞清楚了基本原理,我们就可以尝试自定义一个Java工具类,为Java的Native函数生成签名字符串了,具体代码如下:

    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
  *  COPYRIGHT NOTICE  
  *  Copyright (C) 2014, ticktick <lujun.hust@gmail.com>
  *  http://ticktick.blog.51cto.com/
  *   
  *  @license under the Apache License, Version 2.0 
  *
  *  @file    SignatureGen.java
  *  @brief   Implement a java class for jni signature generate
  *  
  *  @version 1.0     
  *  @author  ticktick
  *  @date    2014/12/15  
 
  */
package  com.ticktick.library;
 
import  java.util.HashMap;
 
public  class  SignatureGen {
 
     public  static  final  HashMap<String,String> Primitives =  new  HashMap<String, String>();
     
     static  {
         Primitives.put(Void. class .getName(), "V" );
         Primitives.put(Boolean. class .getName(), "Z" );
         Primitives.put(Byte. class .getName(), "B" );
         Primitives.put(Character. class .getName(), "C" );
         Primitives.put(Short. class .getName(), "S" );
         Primitives.put(Integer. class .getName(), "I" );
         Primitives.put(Long. class .getName(), "J" );
         Primitives.put(Float. class .getName(), "F" );
         Primitives.put(Double. class .getName(), "D" );            
     }
             
     public  static  String getSignature( Class ret, Class...params ) {
         StringBuilder builder =  new  StringBuilder();
         builder.append( "(" );
         for ( Class param : params ) {
             builder.append(getSignature(param));   
         }      
         builder.append( ")" );
         builder.append(getSignature(ret));
         return  builder.toString();
     }
         
     protected  static  String getSignature( Class param ) {
         
         StringBuilder builder =  new  StringBuilder();
         String name =  "" ;
         if ( param.isArray() ) {
             name = param.getComponentType().getName();
             builder.append( "[" );
         }
         else  {
             name = param.getName();              
         }  
             
         if ( Primitives.containsKey(name) ) {
         builder.append(Primitives.get(name));
         }
         else  {        
             builder.append( "L" +name.replace( "." , "/" )+ ";" );
         }  
       
         return  builder.toString();
     }
}


    该SignatureGen类提供一个支持变参的函数getSignature来获取一个Java函数的签名字符串,第一个参数为函数返回值类型的class对象,变参为每一个函数参数类型的class对象


    具体用法示例如下,打印出不同类型的函数的签名字符串。


1
2
3
4
5
6
7
8
9
10
11
Log.d( "Signature" , "void func() --> "  + SignatureGen.getSignature(Void. class ));
 
Log.d( "Signature" , "boolean func() --> "  + SignatureGen.getSignature(Boolean. class ));
 
Log.d( "Signature" , "int func(boolean a) --> "  + SignatureGen.getSignature(Integer. class ,Boolean. class ));
 
Log.d( "Signature" , "int func(boolean a,String b) --> "  + SignatureGen.getSignature(Integer. class ,Boolean. class ,String. class ));
 
Log.d( "Signature" , "int func(byte[] c) --> "  + SignatureGen.getSignature(Integer. class ,Byte[]. class ));     
 
Log.d( "Signature" , "long func(int n,String str,int arr) -->"  + SignatureGen.getSignature(Long. class ,Integer. class ,String. class ,Integer[]. class ));


    输出结果截屏如下:

    wKioL1SOyGLycSFiAAFsjPzuhjU727.jpg

    

    关于JNI函数签名生成器就介绍到这儿了,原理并不复杂所以我也没有进行过多的分析,希望这个工具类能够在大家今后的项目中派上用场。



本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1590209,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值