Home > database >  How to parse a JNI signature?
How to parse a JNI signature?

Time:12-19

How can I get the general information of a JNI signature (of methods)?

For example,

A method's JNI signature is Lme/jni/Clazz;->demo(Ljava/lang/String;IZ[I[[Z)V,I want to know what the real signature of this method is, which is me.jni.Clazz: void demo(java.lang.String,int,boolean,int[],boolean[][]) in this example. For me, the difficult part is to parse type of method parameters, since it is not easy to split because of the primitive types, which are not separated by ;. In this example, it is IZ[I[[Z.

I wonder if there is any library to solve this problem, or you can offer me some suggestion to solve the problem above.

CodePudding user response:

As I observed in comments, what you're looking at is (mostly) the Java VM's representation of type signatures. Although JNI uses it some, it does not belong to JNI. Its primary documentation is in section 4.3 of the Java VM specification. That provides a formal grammar and a brief prose description.

For me, the difficult part is to parse type of method parameters, since it is not easy to split because of the primitive types, which are not separated by ;.

None of the parameter types are separated from each other by semicolons. The one ; you see is part of the signature of a parameter of type java.lang.String, which overall is Ljava/jang/String;. You do need to read type signatures such as these from left to right, but as long as you do so, they are unambiguous. It's always clear from context where each individual descriptor in a list ends, and the next follows immediately after.

In particular, primitive types have single-letter signatures. They are listed in the linked section of the spec. Array signatures have the form of a [ followed immediately by the signature for the component type. Class (including interface) type signatures have the form of an L, followed by the "binary name" of the type, terminated by a semicolon (;).

Method signatures have the form of a ()-enclosed list of zero or more type descriptors for the parameter types (as above), followed immediately by a descriptor for the return type.

A method's JNI signature is Lme/jni/Clazz;->demo(Ljava/lang/String;IZ[I[[Z)V

Well no, it's not. The kind of signature we're talking describes just the type, not the name or host class. In that example, it is (Ljava/lang/String;IZ[I[[Z)V. To the best of my knowledge, neither the Java VM nor JNI use the full form you present, though its construction seems relatively clear. I could imagine that form being emitted by various tools.

Lme/jni/Clazz; is a signature for reference type me.jni.Class. Presumably, the ->demo indicates a member of that class named "demo", whose type is given by the remainder of the string.

( ... )V is the form of a descriptor for a method returning void (V). The parameter types in this case are

  • Ljava/lang/String; - java.lang.String. We recognize from the L that it is a class type. The (binary) name of the type follows, and we recognize the end of the descriptor via the ;. Binary names are the ordinary Java class names except for using / instead of . as a name separator, encoded in the Java VM's modified UTF-8 encoding.
  • I - int. This is a single-letter code, so we don't need to look around for the end.
  • Z - boolean. This is another single-letter code.
  • [I - array ([) of int (I), a.k.a. int[]. We recognize from the [ that it's an array type, and a descriptor for its element type immediately follows.
  • [[Z - array ([) of (array ([) of boolean (Z)), a.k.a. boolean[][]. This follows the same rule as the previous, recursively.

CodePudding user response:

You could parse the descriptor into a MethodTypeDesc. For example using jshell:

> jshell
|  Welcome to JShell -- Version 18.0.1
|  For an introduction type: /help intro

jshell> import java.lang.constant.*                                                                                     
jshell> MethodTypeDesc.ofDescriptor("(Ljava/lang/String;IZ[I[[Z)V")
$2 ==> MethodTypeDesc[(String,int,boolean,int[],boolean[][])void]

jshell>
  • Related