关键字: JNI, GetMethodID, java.lang.NoSuchMethodError, javap, 内部类
20180816 tjy
转载请注明出处
这几天维护一个app, 需要把一些事情放到so文件中去实现。
在写jni调用java方法的时候,遇到方法的signature错误导致GetMethodID调用抛出java.lang.NoSuchMethodError错误,在解决这个问题上面花了一些时间。
最后各种百度,发现javap能很好的解决这个问题。
javap -s的解释如下,即打印signature. 这个 signature正是写JNI函数需要的。
-s Print internal type signatures
john@john-ThinkPad-Edge-E435:~/workspace/temp$ javap --help
Usage: javap <options> <classes>
where possible options include:
-help --help -? Print this usage message
-version Version information
-v -verbose Print additional information
-l Print line number and local variable tables
-public Show only public classes and members
-protected Show protected/public classes and members
-package Show package/protected/public classes
and members (default)
-p -private Show all classes and members
-c Disassemble the code
-s Print internal type signatures
-sysinfo Show system info (path, size, date, MD5 hash)
of class being processed
-constants Show static final constants
-classpath <path> Specify where to find user class files
-bootclasspath <path> Override location of bootstrap class files
具体JNI的使用方法就不在这里展开了,直接上代码和运行结果,希望能给遇到类似问题的人一个思路。
package com.test;
class Test {
private int mX;
private InternalClass mIc;
public void setX(int x) {
mX = x;
}
public int getX() {
return mX;
}
public void setIc(InternalClass ic) {
mIc = ic;
}
public InternalClass getIc() {
return mIc;
}
//internal class
public class InternalClass {
private String mStr;
public String toString() {
return mStr;
}
}
//main
public static void main() {
Test test = new Test();
}
}
编译之后得到如下的结果:
john@john-ThinkPad-Edge-E435:~/workspace/temp$ javac Test.java
john@john-ThinkPad-Edge-E435:~/workspace/temp$
john@john-ThinkPad-Edge-E435:~/workspace/temp$ ls
Test.class Test$InternalClass.class Test.java Test.java~
javap -s的运行结果如下:
其中有一个setIc函数的参数是个内部类。可以看下内部类的写法。
john@john-ThinkPad-Edge-E435:~/workspace/temp$ javap -s Test.class
Compiled from "Test.java"
class com.test.Test {
com.test.Test();
Signature: ()V
public void setX(int);
Signature: (I)V
public int getX();
Signature: ()I
public void setIc(com.test.Test$InternalClass);
Signature: (Lcom/test/Test$InternalClass;)V
public com.test.Test$InternalClass getIc();
Signature: ()Lcom/test/Test$InternalClass;
public static void main();
Signature: ()V
}
john@john-ThinkPad-Edge-E435:~/workspace/temp$
在看内部类的javap -s的结果:
john@john-ThinkPad-Edge-E435:~/workspace/temp$ javap -s Test\$InternalClass.class
Compiled from "Test.java"
public class com.test.Test$InternalClass {
final com.test.Test this$0;
Signature: Lcom/test/Test;
public com.test.Test$InternalClass(com.test.Test);
Signature: (Lcom/test/Test;)V
public java.lang.String toString();
Signature: ()Ljava/lang/String;
}
john@john-ThinkPad-Edge-E435:~/workspace/temp$