org.jikesrvm.classloader
Class TypeDescriptorParsing

java.lang.Object
  extended by org.jikesrvm.classloader.TypeDescriptorParsing
All Implemented Interfaces:
ClassLoaderConstants

public abstract class TypeDescriptorParsing
extends Object
implements ClassLoaderConstants

A Java class for parsing type descriptors and class names. The class is abstract to eliminate the temptation to instantiate it, since it contains only static methods.

There are five similar kinds of descriptors and names that we have to deal with. We don't have methods for parsing all of them.

In this documentation, I will refer to The Java Native Interface Programmer's Guide and Specification as the JNI Guide.

Some of the types I discuss below are described in 12.3 of the JNI Guide.

Fully-qualified class names and fully-qualified interface names
These are the dot-separated names, such as "java.lang.String" or "java.util.Map".

We can validate these with the static method #isJavaClassName(String) in this class.

JNI Class Descriptor (including array classes),
These include the internal Form of fully-qualified class names and internal form of fully-qualified interface names
These
“It can be derived from a fully qualified class or interface name as defined in The Java Language Specification by substituting the "." character with the "/" character. For example, the JNI class descriptor for java.lang.String is "java/lang/String” Array classes are formed using the "[" character followed by the field descriptor of the element type. The class descrpitor for "int[]" is "[I".

We do not have an interface for parsing these right now.

Field Descriptors
Described in 12.3.3 of the JNI Guide. Examples:
Method Descriptors
Described in 12.3.4 of the JNI guide. To quote:
Method Descriptors are formed by placing the field descriptors of all argument types in a pair of parentheses, and following that by the field descriptor of the return type. There are no spaces or other separator characters between the argument types. "V" is used to denote the void method return type. Constructors use "V" as their return type and use "<init>" as their name.
Example: The method with signature "byte f(int i, String s)" has the Method Descriptor "(ILjava/lang/String;)B"
TypeReference names
Inside Jikes RVM, we use the TypeReference class to represent the reference in some class file to some type (class, interface, primitive, or array). We also use them to represent Void (TypeReference.Void).
TypeReference names are just field descriptors plus "V".


Field Summary
 
Fields inherited from interface org.jikesrvm.classloader.ClassLoaderConstants
ACC_ABSTRACT, ACC_ANNOTATION, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_TRANSIENT, ACC_VOLATILE, APPLICABLE_TO_CLASSES, APPLICABLE_TO_FIELDS, APPLICABLE_TO_METHODS, ArrayTypeCode, BooleanTypeCode, BRIDGE, ByteTypeCode, CharTypeCode, CLASS_INITIALIZED, CLASS_INITIALIZER_FAILED, CLASS_INITIALIZING, CLASS_INSTANTIATED, CLASS_LOADED, CLASS_RESOLVED, CLASS_VACANT, ClassTypeCode, CP_CLASS, CP_DOUBLE, CP_FLOAT, CP_INT, CP_LONG, CP_MEMBER, CP_STRING, CP_UTF, DoubleTypeCode, FloatTypeCode, IntTypeCode, LongTypeCode, ShortTypeCode, TAG_DOUBLE, TAG_FIELDREF, TAG_FLOAT, TAG_INT, TAG_INTERFACE_METHODREF, TAG_LONG, TAG_MEMBERNAME_AND_DESCRIPTOR, TAG_METHODREF, TAG_STRING, TAG_TYPEREF, TAG_UNUSED, TAG_UTF, VARARGS, VoidTypeCode
 
Constructor Summary
TypeDescriptorParsing()
           
 
Method Summary
static boolean isJavaClassName(String s)
          Is the string s a legal name for a Java class or interface?
static boolean isJavaClassNameInternalForm(char[] val, int first, int last)
          Is this the internal form of a Java class name?
private static boolean isJavaPrimitive(byte b)
           
private static boolean isJavaPrimitive(char c)
           
static boolean isValidTypeDescriptor(Atom a)
           
static boolean isValidTypeDescriptor(String s)
           
static boolean isVMIdentifierPart(char c)
          Java 1.5 relaxes the historical convention that class file identifiers (i.e. class, field, and method names) must be drawn from the characters specified by JLS identifiers (i.e. implemented by java.lang.Character.isJavaIdentifierPart()).
static boolean isVMIdentifierStart(char c)
          Java 1.5 relaxes the historical convention that class file identifiers (i.e. class, field, and method names) must be drawn from the characters specified by JLS identifiers (i.e. implemented by java.lang.Character.isJavaIdentifierStart()).
private static void malformed(String msg, String typeName)
          Gripe and throw IllegalArgumentException if we get a malformed type name.
static void validateAsTypeDescriptor(Atom a)
           
static void validateAsTypeDescriptor(String s)
          Validate that the String @param s is a valid type descriptor.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

TypeDescriptorParsing

public TypeDescriptorParsing()
Method Detail

isJavaClassName

public static boolean isJavaClassName(String s)
Is the string s a legal name for a Java class or interface? This will take either fully-qualified names or names that are not fully qualified.

Parameters:
s - The string to check for whether it's a valid name for a Java class. This is a string of the form, for example: "java.lang.String"
Returns:
true if s is valid, false otherwise.

Implementation Question for wiser heads than mine: Would it be more efficient for me to convert this to a char array? That's the way the example in The Java Class Libraries for Character.isJavaIdentifier*() is written. Or is the String.charAt() method inexpensive?


isVMIdentifierStart

public static boolean isVMIdentifierStart(char c)
Java 1.5 relaxes the historical convention that class file identifiers (i.e. class, field, and method names) must be drawn from the characters specified by JLS identifiers (i.e. implemented by java.lang.Character.isJavaIdentifierStart()).

Given that, parsing rules for internal and external VM identifier dictates that identifiers may not contain the following characters: { '.', ';', '[', or '/' }. Method identifiers, excluding <init> and <clinit>, are further constrained to not include the characters '<' or '>'.

To avoid word boundary ambiguity, identifiers are presumed to not begin with a space character. Although not stated explicitly, this remains convention.

This method evaluates whether c is compatible as the starting character for a VM identifier.

Parameters:
c - character to evaluate for VM identifier compatibility
Returns:
boolean true iff c represents a valid VM identifier starting character

isVMIdentifierPart

public static boolean isVMIdentifierPart(char c)
Java 1.5 relaxes the historical convention that class file identifiers (i.e. class, field, and method names) must be drawn from the characters specified by JLS identifiers (i.e. implemented by java.lang.Character.isJavaIdentifierPart()).

Given that, parsing rules for internal and external VM identifier dictates that identifiers may not contain the following characters: { '.', ';', '[', or '/' }. Method identifiers, excluding <init> and <clinit>, are further constrained to not include the characters '<' or '>'.

This method evaluates whether c is compatible as a non-starting character for a VM identifier.

Parameters:
c - character to evaluate for VM identifier compatibility
Returns:
boolean true iff c represents a valid VM identifier non-starting character

isJavaClassNameInternalForm

public static boolean isJavaClassNameInternalForm(char[] val,
                                                  int first,
                                                  int last)
Is this the internal form of a Java class name? (the one with the "/" instead of the "." separating components?) Takes a character array (i.e., an exploded string) and the indices of the first and last characters of the array that are to be checked.


isValidTypeDescriptor

public static boolean isValidTypeDescriptor(String s)

isValidTypeDescriptor

public static boolean isValidTypeDescriptor(Atom a)

validateAsTypeDescriptor

public static void validateAsTypeDescriptor(Atom a)
                                     throws IllegalArgumentException
Throws:
IllegalArgumentException

validateAsTypeDescriptor

public static void validateAsTypeDescriptor(String s)
                                     throws IllegalArgumentException
Validate that the String @param s is a valid type descriptor.

Throws:
IllegalArgumentException - if it isn't.

isJavaPrimitive

private static boolean isJavaPrimitive(char c)

isJavaPrimitive

private static boolean isJavaPrimitive(byte b)

malformed

private static void malformed(String msg,
                              String typeName)
                       throws IllegalArgumentException
Gripe and throw IllegalArgumentException if we get a malformed type name.

Throws:
IllegalArgumentException