如何获取字段或方法的JNI风格签名字符串?

问题描述 投票:0回答:2

我正在尝试检查 Java 类并自动检索其所有方法和字段,以便我可以通过 Android 上的 JNI 调用它们。但是,我不知道如何以编程方式实际获取文本签名字符串;我知道如何从命令行通过

javap -s
获取它,但我想从我的程序中获取它。

我能找到的最接近的是使用

clazz.getMethods()
获取各个方法,然后使用
Method.toGenericString()
获取人类可读的字符串,但该字符串的格式类似于 Java 代码签名(例如
public int someMethod(int foo, java.lang.String bar)
),而我真的只是想要 JNI 风格的签名(例如
(ILjava/lang/String;)I
),因为我需要该字符串从 JNI 调用
getMethodID()
,并且我已经有了一个完美的解析器,可以首先解析这些 JNI 签名。

我可以手动维护我真正关心的从 JNI 访问的类的绑定,但我宁愿让所有事情尽可能自动处理;毕竟,代码越少越好。

我确实找到了 ASM,它为此提供了辅助方法,但它似乎是一个字节码生成框架,我不确定它是否与 Android 兼容。

或者,换句话说,给定以下课程:

class SomeClass {
    String foo(int bar) { return "This is foo " + bar; }
}

我想创建一个名为

ClassInspector
的类,它可以执行以下操作:

ClassInspector ci = new ClassInspector(SomeClass.class);
int n = ci.getMethodCount(); // returns 1
String name = ci.getMethodName(0); // returns "foo"
String sig = ci.getMethodSignature(0); // returns "(I)Ljava/lang/string;"

也就是说,我希望能够从 Java 内部获取

javap -s
的输出,以便我可以从本机端调用 Java 方法。

java android android-ndk java-native-interface
2个回答
1
投票

我遇到了同样的问题,但找不到“干净”的解决方案。

最后,我决定创建一个具有相同方法但声明为原生的虚拟类。 然后我使用 javah 创建头文件,并从该头文件中获取签名。

我知道它看起来不太好......但我没有找到更好的选择(除了根据方法属性“手动”创建它)。


0
投票

我有类似的需求,并通过从

JavapTask.java
工具的源代码中挖掘
javap
找到了解决方案。

这是一个可以满足您要求的代码片段:

public class Test {
    String foo(int bar) { return "This is foo " + bar; }

    public static void main(String[] args) {
        Class<?> c = Test.class;
        java.lang.reflect.Method methods[] = c.getDeclaredMethods();
        System.out.println("Class : " + c.getName());
        System.out.println("Number of methods : " + methods.length);
        for (java.lang.reflect.Method m : methods) {
            java.lang.invoke.MethodType mt = java.lang.invoke.MethodType.methodType(m.getReturnType(), m.getParameterTypes());
            System.out.println(m.getName() + " : " + mt.toMethodDescriptorString());
        }
    }
}

它打印出以下内容:

Class : Test
Number of methods : 2
main : ([Ljava/lang/String;)V
foo : (I)Ljava/lang/String;
© www.soinside.com 2019 - 2024. All rights reserved.