javah命令 无法确定surface的签名

简介: 笔记

使用AndroidStudio进行JNI开发时,编写好了Native方法的java文件,使用javah生成头文件报错:


2.png

image.png

先上解决方案


修改javah的-classpath参数

我原来的是:

-classpath . -jni -encoding UTF-8 -d $ModuleFileDir$/src/main/cpp/include $FileClass$

修改为:

-classpath D:\Android\Sdk\platforms\android-28\android.jar;. -jni -encoding UTF-8 -d $ModuleFileDir$/src/main/cpp/include $FileClass$

一定要注意D:\Android\Sdk\platforms\android-28\android.jar;.分号后面带一个英文句号。

另外,类似的问题该方法通用

其实还有一种解决方案(不推荐):

就是修改Java代码,把Surface类型改为Object类型,只不过要自己做一些类型转换的工作,增加了代码工作量。


原因分析


我们应该知道,javah生成头文件需要给方法生成签名,而签名的原理是依据类的完整包名来的,所以究其原因是javah的-classpath参数配置错误,导致找不到Surface类。

我们先来看一下javah的用法:

C:\Users\bian>javah
用法:
  javah [options] <classes>
其中, [options] 包括:
  -o <file>                输出文件 (只能使用 -d 或 -o 之一)
  -d <dir>                 输出目录
  -v  -verbose             启用详细输出
  -h  --help  -?           输出此消息
  -version                 输出版本信息
  -jni                     生成 JNI 样式的标头文件 (默认值)
  -force                   始终写入输出文件
  -classpath <path>        从中加载类的路径
  -cp <path>               从中加载类的路径
  -bootclasspath <path>    从中加载引导类的路径
<classes> 是使用其全限定名称指定的
(例如, java.lang.Object)。

-d-o

这两个参数用于设置生成的C\C++头文件的指定,该两参数选项不能同时使用,-d是为中的每个有JNI方法的java类都生成一个头文件,并存放在-d指定的目录中,-o则是生成的所有JNI方法的头文件都放在-o指定的文件中。

-jni

表示用于生成JNI风格的C\C++头文件,默认该参数就是开启的。

-classpath

使用-classpath后JDK将不再使用CLASSPATH中的类搜索路径,如果-classpath和CLASSPATH都没有设置,则JDK使用当前路径(.)作为类搜索路径。

推荐使用-classpath来定义JDK要搜索的类路径,而不要使用环境变量CLASSPATH的搜索路径,以减少多个项目同时使用CLASSPATH时存在的潜在冲突。例如应用1要使用a1.0.jar中的类G,应用2要使用 a2.0.jar中的类G,a2.0.jar是a1.0.jar的升级包,当a1.0.jar,a2.0.jar都在CLASSPATH中,JDK搜索到第一个包中的类G时就停止搜索,如果应用1应用2的虚拟机都从CLASSPATH中搜索,就会有一个应用得不到正确版本的类G。

-verbose

该参数,将显示javah命令搜索和装置类文件的详细过程。

仔细看-classpath参数的解释就明白了吧,原来是我之前的classpath .是从当前路径.开始查找类的,当前类是哪里呢?从前面的图片中写出来了,是jre环境C:\Android\AndroidStudio\jre/bin/javah,所以只能找到java类,不能找到安卓的类。我们把安卓SDK路径添加进去那么javah就能够找到了。

还要注意classpath的配置语法,多个路径使用分号;隔开,所以解决方案就是前面所说的配置-classpath参数为D:\Android\Sdk\platforms\android-28\android.jar;.


总结


根据javah生成头文件的原理我们可以知道,任何参与JNI的类,都必须知道完整的包名路径。再假设我们使用了第三方库,有一些自定义的类,那么我们也应该把这个类的路径配置到-classpath参数中去。


目录
相关文章
|
JavaScript Shell 程序员
Electron如何调用.exe文件并传递参数
Electron如何调用.exe文件并传递参数
818 0
Electron如何调用.exe文件并传递参数
|
2月前
|
算法 Java Android开发
安卓逆向 -- 调用其他APK的SO文件
安卓逆向 -- 调用其他APK的SO文件
17 0
|
API vr&ar Python
编写批处理文件,调用ffmpeg抽帧
编写批处理文件,调用ffmpeg抽帧
189 0
编写批处理文件,调用ffmpeg抽帧
|
C++ iOS开发
iOS开发 -- 在Xcode中引入cpp文件,并调用cpp文件中的方法
iOS开发 -- 在Xcode中引入cpp文件,并调用cpp文件中的方法
646 0
iOS开发 -- 在Xcode中引入cpp文件,并调用cpp文件中的方法
|
Java 开发工具 C++
|
iOS开发
Xcode编译后运行程序Killed: -9,因为签名有问题
Xcode编译后运行程序Killed: -9,因为签名有问题
208 0
|
Android开发
【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | exec_utils.cc 中执行 Dex 编译为 Oat 文件的 Exec 和 ExecAndReturnC函数 )
【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | exec_utils.cc 中执行 Dex 编译为 Oat 文件的 Exec 和 ExecAndReturnC函数 )
131 0
|
Java Android开发 C++
【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )(二)
【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )(二)
153 0
|
Java Android开发 C++
【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )(一)
【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )(一)
175 0
【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )(一)
|
算法 Java Android开发
APK重新签名方法
Android使用SHA1-RSA算法进行签名。可通过eclipse插件进行,可以通过keytool和jarsigner 用命令行执行,也可以在源码下进行签名。 第一种:通过使用eclipse进行签名。
1689 0