## Metagnostic home
| # JNIPort for Dolphin Smalltalk
Overview Contents Players Layers Examples Configuration InFAQ Changes Licence Back to Goodies | # Type Names and Signatures In Java, classes are named in dot-separated form, such as `java.lang.String`; primitive types are just called `int`, `double`, etc; and names for array types are constructed by appending `[]` to the name of the base type as many times as necessary. It will probably not surprise you to learn that JNI and the JVM do not work this way. Actually there are two, subtly different, naming schemes used by both the JVM and JNI. The good news is that if you use the top-level of JNIPort then you won't have to worry about either of them because the generated class wrappers know about JNI names. The bad news is that if you want to use the JNI wrapper layer or the Java base layer, then you are going to have to get your head around some of this stuff. Sorry! One scheme is used by JNI and the JVM for referring to types by name, the other is used by when specifying the signatures of methods. (By the way, there is a third naming scheme in the Java world: that understood by the Java method, `java.lang.Class.forName()` — its rules are different again, but there's no need to go into that here.) ## JVM/JNI Type Names In contexts where the Java runtime expects the name of a type (e.g. the JNI function `FindClass()`), then the names of Classes and Interfaces are formed by replacing all the dots in the fully qualified Java name by slashes. E.g:
Fully qualified Java class name | JVM/JNI type name
--- | ---
`java.lang.String` | `java/lang/String`
`java.util.Map` | `java/util/Map`
If the type is a primitive type (`int`, `boolean`, etc) then there is no way to name the type directly (this is an inconsistency in the naming scheme). If the type is an array type (including arrays of primitive types), then the rules are the same as for JNI type signatures. See below for the details, but some examples are:
Fully qualified Java array class name | JVM/JNI type name
--- | ---
`java.lang.String[]` | `[Ljava/lang/String;`
`int[]` | `[I`
`long[][]` | `[[J`
If you are using the Java Base layer or above, then you don't need to worry about JVM/JNI type names, since the system understands how to find a class object given a name in “normal” Java format. (It also understands the JVM/JNI format, but you aren't forced to use that.) The way to find a class by name (at this level) is to use the `JVM>>findClass:` method. It takes a `Symbol` or `String` argument (`Symbol` is more efficient), e.g:
Fully qualified Java type name | Argument to `JVM>>findClass:`
--- | ---
`java.lang.String` | `#'java.lang.String'`
`java.util.Map` | `#'java.util.Map'`
`boolean` | `#boolean`
`java.lang.String[]` | `#'java.lang.String[]'`
`double[][]` | `#'double[][]'`
## JVM/JNI Signatures If you are using the 'Java Base' layer of JNIPort, then you have to specify the signature of any method you call, or field you access. It may help to know that the Smalltalk objects that wrap Java's `java.lang.reflect.Method`, `.Field`, and `.Constructor` object know how to compute their own signatures. (And why the Java objects themselves can't do it is more than I can imagine…) ### Method Signatures In Java, methods can be overloaded — that is you can have several different methods with the same name, but which take arguments of different types. For instance, if you use the method `java.lang.Object.wait()`, then the compiler will determine which of the three versions of `wait()` you mean from the types of the arguments you supply (if any). What is really happening (i.e. what the JVM sees) is that a Java method is named by a pair of strings, one is the “normal” name of the method, the other is the signature. The signature of a method is a string that describes the return type of the method and the (static) types of its arguments. When talking to the JVM, you never refer to a method just by the “normal” name, you always give both the name and the signature. A method's signature is written: `(<argument types>)<return type>` where the `<argument types>` substring is formed by concatenating the signature names of the types of the arguments (if there are any), and the `<return type>` is just the signature name of the return type. Type signatures are described below, but here are some examples of complete signature strings for a few methods;
Method | Signature
--- | ---
`void doNothing() { }` | `()V`
`int returnOne() { return 1; }` | `()I`
`void main(String[] args) { ... }` | `([Ljava/lang/String;)V`
`long sum(int[] n) { ... }` | `([I)J`
`Point square(Point p) { ... }` | `(Ljava/awt/Point;)Ljava/awt/Point;`
Java constructors (which are not, technically, methods at all) also have signatures; they are used to distinguish between the different forms of the constructor. The `<argument types>` substring is constructed in the usual way, and the return type is always 'V'. There is no real need to name constructors in JNIPort (since instances are always created via special JNI functions), but they are considered to have the name `“<init>”`. You will only need to use method signatures if you are using the Java Base level of JNIPort to call methods. The higher level automatically works out the signatures when it generates wrapper methods. ### Field Signatures One possibly surprising fact is that in JNI (and at the JVM level) Java fields have signatures too, and in fact it is possible to have more than one member field with the same name (but holding different types). The signature of a field is just the signature of the type that it is (statically) declared to hold. As with method signatures, you will need to use member signatures if you are using the Java Base level of JNIPort to read/write fields. (The higher levels automatically work out the signatures when the accessor methods are generated). ### Type Signatures The signature names of primitive types are single letters as follows:
Primitive type | Signature
--- | ---
`byte` | `B`
`char` | `C`
`double` | `D`
`float` | `F`
`int` | `I`
`long` | `J`
`short` | `S`
`void` | `V`
`boolean` | `Z`
(Note the irregularities for `long` and `boolean`) So a method that takes a `char` and a `boolean`, and returns another `char`, e.g:
    	char convertCase(char ch, boolean uppercase) {...}
would be named by the string “convertCase” and have signature “(CZ)C”, since the signatures of the arguments are 'C' and 'Z' respectively, and the signature of the return-type is 'Z'. A method that takes no arguments and returns void has signature “()V”. The signature of a class is the letter 'L' followed by the fully-qualified class name with the dots replaced by slashes, all followed by a semi-colon. E.g:
Class | Signature
--- | ---
`java.lang.String` | `Ljava/lang/String;`
`java.awt.Point` | `Ljava/awt/Point;`
The signature of an array class is the letter '[' followed by the signature of the element class (which may itself be another array class), e.g:
Array class | Signature
--- | ---
`java.lang.String[]` | `[Ljava/lang/String;`
`java.awt.Point[][]` | `[[Ljava/awt/Point;`
`int[]` | `[I`
`boolean[][][]` | `[[[Z`

Copyright © Chris Uppal, 2003-2005

Java, JNI (probably), JVM (possibly), and God knows what else, are trademarks of Sun Microsystems, Inc.