安卓之JNI 和 NDK编程(九)javah 和 javap生成方法的头文件、方法的签名

 

文章目录

一、javah

1、生成 .h 文件

2、把 .h 文件生成到c/c++指定目录

3、命令复习

二、javap

1、javap的用途

2、获取java方法的签名

3、获取java方法的签名(选看)

4、AS插件获取java方法的签名

5、命令复习


javah 和 javap,这两个工具,都是jdk的bin目录下提供的命令,那么为什么要用这两个工具呢?

一、javah

我们知道有几个东西是很难写的,如当c++要提供一个接口给java的时候的方法名

Java_com_luminal_ndktest_Jni_getStringFromJni,很长有时候也会很容易写错,这个时候我们可以用到javah,

javah会去搜索这个类里面所有的native方法,然后会帮你生成c++方法的头文件,也就是方法声明。

1、生成 .h 文件

如我们在Android Studio的Terminal窗口输入如下命令:

//查看当前目录
//ls
//切换目录
//cd app/src/main/java/
//生成.h文件
//javah com.luminal.ndktest.Jni

如下图,它会生成一个 com_luminal_ndktest_Jni.h 的文件

com_luminal_ndktest_Jni.h 文件的内容如下,它自动帮我们生成了头文件

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

#ifndef _Included_com_luminal_ndktest_Jni
#define _Included_com_luminal_ndktest_Jni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_luminal_ndktest_Jni
 * Method:    getStringFromJni
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_luminal_ndktest_Jni_getStringFromJni
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

我们回头做 jni/ndk 开发,把这些生成c/c++方法的头文件,也就是方法声明,复制到.cpp文件里面进行实现即可

2、把 .h 文件生成到c/c++指定目录

刚在生成的 com_luminal_ndktest_Jni.h 文件,是在java目录,它是java代码的目录,我们可以把它放到c/c++代码特有的目录,这时我们可以输入如下命令:

//删除.h文件
//rm com_luminal_ndktest_Jni.h
//指定目录生成.h文件
//javah -d ../cpp com.luminal.ndktest.Jni

如下图,在cpp目录下生成了 com_luminal_ndktest_Jni.h 文件

如果要删除 com_luminal_ndktest_Jni.h 文件,可执行如下命令

//指定目录删除.h文件
//rm ../cpp/com_luminal_ndktest_Jni.h

3、命令复习

javah 用于生成 native接口定义(在C/C++中的),比如:

javah -d ../cpp/包名+类名   即javah -d ../cpp/com.luminal.ndktest.Jni

javah -d ../cpp/ 表示你的头文件要生成到哪里去

com.luminal.ndktest.Jni  表示你的那个类里面有nativie接口

//查看当前目录
//ls

//切换目录
//cd app/src/main/java/

//生成.h文件
//javah com.luminal.ndktest.Jni

//删除.h文件
//rm com_luminal_ndktest_Jni.h

//指定目录生成.h文件
//javah -d ../cpp com.luminal.ndktest.Jni

//指定目录删除.h文件
//rm ../cpp/com_luminal_ndktest_Jni.h

二、javap

1、javap的用途

我们上面讲了javah的作用用途,那么javap是拿来干什么的?

javap用来反编译,同时用于生成java函数(方法)的签名

2、获取java方法的签名

如博文:安卓之JNI 和 NDK编程(七)c++调用java代码 中这段代码方法参数3,方法签名到底是怎么来的?

//3、获取方法(函数)
//参数1:对象名。  参数2:方法名
//参数3:方法签名。"()V" 括号表示callByCpp方法没有参数,V表示callByCpp方法没有返回值,返回值为void
jmethodID methodID = env->GetMethodID(jniclass, "callByCpp", "()V");

上面我们执行javah命令以后,它现在在java目录下,我们可以切换到项目根目录( 我的项目名称ndkCode),查找到 Jni类 (用来封装c/c++的native方法的类)  的class文件

bogon:java luminal$ cd ..
bogon:main luminal$ ls
AndroidManifest.xml     cpp                     java                    res
bogon:main luminal$ cd ..
bogon:src luminal$ ls
androidTest     main            test
bogon:src luminal$ cd ..
bogon:app luminal$ ls
CMakeLists.txt          app.iml                 build                   build.gradle            libs                    proguard-rules.pro      src
bogon:app luminal$ cd ..
bogon:ndkCode luminal$ ls
app                     code.iml                gradle.properties       gradlew.bat             ndkCode.iml
build.gradle            gradle                  gradlew                 local.properties        settings.gradle
bogon:ndkCode luminal$ find . -name "Jni.class"
./app/build/intermediates/incremental-verifier/debug/com/luminal/ndktest/Jni.class
./app/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/luminal/ndktest/Jni.class
./app/build/intermediates/transforms/instantRun/debug/0/com/luminal/ndktest/Jni.class

上面找到三个Jni.class文件,然后我们用 javap -s  命令执行javac目录下的,即可看到相关方法的签名

javap -s app/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/luminal/ndktest/Jni.class

bogon:ndkCode luminal$ javap -s app/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/luminal/ndktest/Jni.class
Compiled from "Jni.java"
public class com.luminal.ndktest.Jni {
  public com.luminal.ndktest.Jni();
    descriptor: ()V

  public static com.luminal.ndktest.Jni instance();
    descriptor: ()Lcom/luminal/ndktest/Jni;

  public native java.lang.String getStringFromJni();
    descriptor: ()Ljava/lang/String;

  public void callByCpp();
    descriptor: ()V

  static {};
    descriptor: ()V
}

3、获取java方法的签名(选看)

我们也可以把三个目录的Jni.class都执行看看:

javap -s app/build/intermediates/incremental-verifier/debug/com/luminal/ndktest/Jni.class

javap -s app/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/luminal/ndktest/Jni.class

javap -s app/build/intermediates/transforms/instantRun/debug/0/com/luminal/ndktest/Jni.class
 

bogon:ndkCode luminal$ javap -s app/build/intermediates/incremental-verifier/debug/com/luminal/ndktest/Jni.class
Compiled from "Jni.java"
public class com.luminal.ndktest.Jni {
  public com.luminal.ndktest.Jni();
    descriptor: ()V

  public static com.luminal.ndktest.Jni instance();
    descriptor: ()Lcom/luminal/ndktest/Jni;

  public native java.lang.String getStringFromJni();
    descriptor: ()Ljava/lang/String;

  public void callByCpp();
    descriptor: ()V

  static {};
    descriptor: ()V
}



bogon:ndkCode luminal$ javap -s app/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/luminal/ndktest/Jni.class
Compiled from "Jni.java"
public class com.luminal.ndktest.Jni {
  public com.luminal.ndktest.Jni();
    descriptor: ()V

  public static com.luminal.ndktest.Jni instance();
    descriptor: ()Lcom/luminal/ndktest/Jni;

  public native java.lang.String getStringFromJni();
    descriptor: ()Ljava/lang/String;

  public void callByCpp();
    descriptor: ()V

  static {};
    descriptor: ()V
}



bogon:ndkCode luminal$ javap -s app/build/intermediates/transforms/instantRun/debug/0/com/luminal/ndktest/Jni.class
Compiled from "Jni.java"
public class com.luminal.ndktest.Jni {
  public static volatile transient com.android.tools.ir.runtime.IncrementalChange $change;
    descriptor: Lcom/android/tools/ir/runtime/IncrementalChange;
  public static final long serialVersionUID;
    descriptor: J
  public com.luminal.ndktest.Jni();
    descriptor: ()V

  public static com.luminal.ndktest.Jni instance();
    descriptor: ()Lcom/luminal/ndktest/Jni;

  public native java.lang.String getStringFromJni();
    descriptor: ()Ljava/lang/String;

  public void callByCpp();
    descriptor: ()V

  public static {};
    descriptor: ()V

  public static java.lang.Object access$super(com.luminal.ndktest.Jni, java.lang.String, java.lang.Object...);
    descriptor: (Lcom/luminal/ndktest/Jni;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;

  com.luminal.ndktest.Jni(java.lang.Object[], com.android.tools.ir.runtime.InstantReloadException);
    descriptor: ([Ljava/lang/Object;Lcom/android/tools/ir/runtime/InstantReloadException;)V
}
bogon:ndkCode luminal$ 

4、AS插件获取java方法的签名

在jni/ndk开发的时候,经常要看一个方法的方法签名,我们讲了可以用命令行来查看,下面我们将讲讲在AS之下有一个插件,可以很方便地在AS内查看java方法的签名,打开Android Studio->Preferences->Plugins,点击下面的Browse respositories,搜索jclasslib,如下图,当然由于我的ide最近更新到AndroidStudio 3.5,它如下图:

其它可参考博文:

安卓开发学习之在Android Studio下查看java类的字节码

https://blog.csdn.net/qq_37475168/article/details/80391821

 

5、命令复习

//返回上一个目录
//cd ..

//搜索目录下的某个文件
//find -name "Jni.class" //【此命令在mac上有误】
//find . -name "Jni.class" //【mac能使用】

//获取java方法签名
javap -s xxx.class

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

被开发耽误的大厨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值