|
|
|
@ -146,10 +146,6 @@ public class Type { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private final int valueEnd; |
|
|
|
private final int valueEnd; |
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Constructors
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Constructs a reference type. |
|
|
|
* Constructs a reference type. |
|
|
|
* |
|
|
|
* |
|
|
|
@ -167,6 +163,10 @@ public class Type { |
|
|
|
this.valueEnd = valueEnd; |
|
|
|
this.valueEnd = valueEnd; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Methods to get Type(s) from a descriptor, a reflected Method or Constructor, other types, etc.
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the {@link Type} corresponding to the given type descriptor. |
|
|
|
* Returns the {@link Type} corresponding to the given type descriptor. |
|
|
|
* |
|
|
|
* |
|
|
|
@ -174,40 +174,7 @@ public class Type { |
|
|
|
* @return the {@link Type} corresponding to the given type descriptor. |
|
|
|
* @return the {@link Type} corresponding to the given type descriptor. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static Type getType(final String typeDescriptor) { |
|
|
|
public static Type getType(final String typeDescriptor) { |
|
|
|
return getType(typeDescriptor, 0, typeDescriptor.length()); |
|
|
|
return getTypeInternal(typeDescriptor, 0, typeDescriptor.length()); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the {@link Type} corresponding to the given internal name. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param internalName an internal name. |
|
|
|
|
|
|
|
* @return the {@link Type} corresponding to the given internal name. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static Type getObjectType(final String internalName) { |
|
|
|
|
|
|
|
return new Type( |
|
|
|
|
|
|
|
internalName.charAt(0) == '[' ? ARRAY : INTERNAL, internalName, 0, internalName.length()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the {@link Type} corresponding to the given method descriptor. Equivalent to <code> |
|
|
|
|
|
|
|
* Type.getType(methodDescriptor)</code>. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param methodDescriptor a method descriptor. |
|
|
|
|
|
|
|
* @return the {@link Type} corresponding to the given method descriptor. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static Type getMethodType(final String methodDescriptor) { |
|
|
|
|
|
|
|
return new Type(METHOD, methodDescriptor, 0, methodDescriptor.length()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the method {@link Type} corresponding to the given argument and return types. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param returnType the return type of the method. |
|
|
|
|
|
|
|
* @param argumentTypes the argument types of the method. |
|
|
|
|
|
|
|
* @return the method {@link Type} corresponding to the given argument and return types. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static Type getMethodType(final Type returnType, final Type... argumentTypes) { |
|
|
|
|
|
|
|
return getType(getMethodDescriptor(returnType, argumentTypes)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -264,6 +231,60 @@ public class Type { |
|
|
|
return getType(getMethodDescriptor(method)); |
|
|
|
return getType(getMethodDescriptor(method)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the type of the elements of this array type. This method should only be used for an |
|
|
|
|
|
|
|
* array type. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Returns the type of the elements of this array type. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public Type getElementType() { |
|
|
|
|
|
|
|
final int numDimensions = getDimensions(); |
|
|
|
|
|
|
|
return getTypeInternal(valueBuffer, valueBegin + numDimensions, valueEnd); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the {@link Type} corresponding to the given internal name. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param internalName an internal name. |
|
|
|
|
|
|
|
* @return the {@link Type} corresponding to the given internal name. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static Type getObjectType(final String internalName) { |
|
|
|
|
|
|
|
return new Type( |
|
|
|
|
|
|
|
internalName.charAt(0) == '[' ? ARRAY : INTERNAL, internalName, 0, internalName.length()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the {@link Type} corresponding to the given method descriptor. Equivalent to <code> |
|
|
|
|
|
|
|
* Type.getType(methodDescriptor)</code>. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param methodDescriptor a method descriptor. |
|
|
|
|
|
|
|
* @return the {@link Type} corresponding to the given method descriptor. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static Type getMethodType(final String methodDescriptor) { |
|
|
|
|
|
|
|
return new Type(METHOD, methodDescriptor, 0, methodDescriptor.length()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the method {@link Type} corresponding to the given argument and return types. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param returnType the return type of the method. |
|
|
|
|
|
|
|
* @param argumentTypes the argument types of the method. |
|
|
|
|
|
|
|
* @return the method {@link Type} corresponding to the given argument and return types. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static Type getMethodType(final Type returnType, final Type... argumentTypes) { |
|
|
|
|
|
|
|
return getType(getMethodDescriptor(returnType, argumentTypes)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the argument types of methods of this type. This method should only be used for method |
|
|
|
|
|
|
|
* types. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return the argument types of methods of this type. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public Type[] getArgumentTypes() { |
|
|
|
|
|
|
|
return getArgumentTypes(getDescriptor()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the {@link Type} values corresponding to the argument types of the given method |
|
|
|
* Returns the {@link Type} values corresponding to the argument types of the given method |
|
|
|
* descriptor. |
|
|
|
* descriptor. |
|
|
|
@ -307,7 +328,7 @@ public class Type { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
argumentTypes[currentArgumentTypeIndex++] = |
|
|
|
argumentTypes[currentArgumentTypeIndex++] = |
|
|
|
getType(methodDescriptor, currentArgumentTypeOffset, currentOffset); |
|
|
|
getTypeInternal(methodDescriptor, currentArgumentTypeOffset, currentOffset); |
|
|
|
} |
|
|
|
} |
|
|
|
return argumentTypes; |
|
|
|
return argumentTypes; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -327,6 +348,16 @@ public class Type { |
|
|
|
return types; |
|
|
|
return types; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the return type of methods of this type. This method should only be used for method |
|
|
|
|
|
|
|
* types. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return the return type of methods of this type. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public Type getReturnType() { |
|
|
|
|
|
|
|
return getReturnType(getDescriptor()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the {@link Type} corresponding to the return type of the given method descriptor. |
|
|
|
* Returns the {@link Type} corresponding to the return type of the given method descriptor. |
|
|
|
* |
|
|
|
* |
|
|
|
@ -347,7 +378,7 @@ public class Type { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return getType(methodDescriptor, currentOffset + 1, methodDescriptor.length()); |
|
|
|
return getTypeInternal(methodDescriptor, currentOffset + 1, methodDescriptor.length()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -360,47 +391,6 @@ public class Type { |
|
|
|
return getType(method.getReturnType()); |
|
|
|
return getType(method.getReturnType()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Computes the size of the arguments and of the return value of a method. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param methodDescriptor a method descriptor. |
|
|
|
|
|
|
|
* @return the size of the arguments of the method (plus one for the implicit this argument), |
|
|
|
|
|
|
|
* argumentsSize, and the size of its return value, returnSize, packed into a single int i = |
|
|
|
|
|
|
|
* {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code |
|
|
|
|
|
|
|
* i >> 2}, and returnSize to {@code i & 0x03}). |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static int getArgumentsAndReturnSizes(final String methodDescriptor) { |
|
|
|
|
|
|
|
int argumentsSize = 1; |
|
|
|
|
|
|
|
// Skip the first character, which is always a '('.
|
|
|
|
|
|
|
|
int currentOffset = 1; |
|
|
|
|
|
|
|
int currentChar = methodDescriptor.charAt(currentOffset); |
|
|
|
|
|
|
|
// Parse the argument types and compute their size, one at a each loop iteration.
|
|
|
|
|
|
|
|
while (currentChar != ')') { |
|
|
|
|
|
|
|
if (currentChar == 'J' || currentChar == 'D') { |
|
|
|
|
|
|
|
currentOffset++; |
|
|
|
|
|
|
|
argumentsSize += 2; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
while (methodDescriptor.charAt(currentOffset) == '[') { |
|
|
|
|
|
|
|
currentOffset++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (methodDescriptor.charAt(currentOffset++) == 'L') { |
|
|
|
|
|
|
|
while (methodDescriptor.charAt(currentOffset++) != ';') { |
|
|
|
|
|
|
|
// Skip the argument descriptor content.
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
argumentsSize += 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
currentChar = methodDescriptor.charAt(currentOffset); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
currentChar = methodDescriptor.charAt(currentOffset + 1); |
|
|
|
|
|
|
|
if (currentChar == 'V') { |
|
|
|
|
|
|
|
return argumentsSize << 2; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
int returnSize = (currentChar == 'J' || currentChar == 'D') ? 2 : 1; |
|
|
|
|
|
|
|
return argumentsSize << 2 | returnSize; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the {@link Type} corresponding to the given field or method descriptor. |
|
|
|
* Returns the {@link Type} corresponding to the given field or method descriptor. |
|
|
|
* |
|
|
|
* |
|
|
|
@ -411,7 +401,7 @@ public class Type { |
|
|
|
* descriptorBuffer. |
|
|
|
* descriptorBuffer. |
|
|
|
* @return the {@link Type} corresponding to the given type descriptor. |
|
|
|
* @return the {@link Type} corresponding to the given type descriptor. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private static Type getType( |
|
|
|
private static Type getTypeInternal( |
|
|
|
final String descriptorBuffer, final int descriptorBegin, final int descriptorEnd) { |
|
|
|
final String descriptorBuffer, final int descriptorBegin, final int descriptorEnd) { |
|
|
|
switch (descriptorBuffer.charAt(descriptorBegin)) { |
|
|
|
switch (descriptorBuffer.charAt(descriptorBegin)) { |
|
|
|
case 'V': |
|
|
|
case 'V': |
|
|
|
@ -444,45 +434,9 @@ public class Type { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// Accessors
|
|
|
|
// Methods to get class names, internal names or descriptors.
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the sort of this type. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE}, {@link #SHORT}, {@link |
|
|
|
|
|
|
|
* #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY}, {@link #OBJECT} or |
|
|
|
|
|
|
|
* {@link #METHOD}. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public int getSort() { |
|
|
|
|
|
|
|
return sort == INTERNAL ? OBJECT : sort; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the number of dimensions of this array type. This method should only be used for an |
|
|
|
|
|
|
|
* array type. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return the number of dimensions of this array type. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public int getDimensions() { |
|
|
|
|
|
|
|
int numDimensions = 1; |
|
|
|
|
|
|
|
while (valueBuffer.charAt(valueBegin + numDimensions) == '[') { |
|
|
|
|
|
|
|
numDimensions++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return numDimensions; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the type of the elements of this array type. This method should only be used for an |
|
|
|
|
|
|
|
* array type. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Returns the type of the elements of this array type. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public Type getElementType() { |
|
|
|
|
|
|
|
final int numDimensions = getDimensions(); |
|
|
|
|
|
|
|
return getType(valueBuffer, valueBegin + numDimensions, valueEnd); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the binary name of the class corresponding to this type. This method must not be used |
|
|
|
* Returns the binary name of the class corresponding to this type. This method must not be used |
|
|
|
* on method types. |
|
|
|
* on method types. |
|
|
|
@ -535,42 +489,16 @@ public class Type { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the argument types of methods of this type. This method should only be used for method |
|
|
|
* Returns the internal name of the given class. The internal name of a class is its fully |
|
|
|
* types. |
|
|
|
* qualified name, as returned by Class.getName(), where '.' are replaced by '/'. |
|
|
|
* |
|
|
|
|
|
|
|
* @return the argument types of methods of this type. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public Type[] getArgumentTypes() { |
|
|
|
|
|
|
|
return getArgumentTypes(getDescriptor()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the return type of methods of this type. This method should only be used for method |
|
|
|
|
|
|
|
* types. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return the return type of methods of this type. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public Type getReturnType() { |
|
|
|
|
|
|
|
return getReturnType(getDescriptor()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the size of the arguments and of the return value of methods of this type. This method |
|
|
|
|
|
|
|
* should only be used for method types. |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* @return the size of the arguments of the method (plus one for the implicit this argument), |
|
|
|
* @param clazz an object or array class. |
|
|
|
* argumentsSize, and the size of its return value, returnSize, packed into a single int i = |
|
|
|
* @return the internal name of the given class. |
|
|
|
* {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code |
|
|
|
|
|
|
|
* i >> 2}, and returnSize to {@code i & 0x03}). |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public int getArgumentsAndReturnSizes() { |
|
|
|
public static String getInternalName(final Class<?> clazz) { |
|
|
|
return getArgumentsAndReturnSizes(getDescriptor()); |
|
|
|
return clazz.getName().replace('.', '/'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Conversion to type descriptors
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the descriptor corresponding to this type. |
|
|
|
* Returns the descriptor corresponding to this type. |
|
|
|
* |
|
|
|
* |
|
|
|
@ -590,57 +518,6 @@ public class Type { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the descriptor corresponding to the given argument and return types. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param returnType the return type of the method. |
|
|
|
|
|
|
|
* @param argumentTypes the argument types of the method. |
|
|
|
|
|
|
|
* @return the descriptor corresponding to the given argument and return types. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) { |
|
|
|
|
|
|
|
StringBuilder stringBuilder = new StringBuilder(); |
|
|
|
|
|
|
|
stringBuilder.append('('); |
|
|
|
|
|
|
|
for (int i = 0; i < argumentTypes.length; ++i) { |
|
|
|
|
|
|
|
argumentTypes[i].appendDescriptor(stringBuilder); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
stringBuilder.append(')'); |
|
|
|
|
|
|
|
returnType.appendDescriptor(stringBuilder); |
|
|
|
|
|
|
|
return stringBuilder.toString(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Appends the descriptor corresponding to this type to the given string buffer. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param stringBuilder the string builder to which the descriptor must be appended. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private void appendDescriptor(final StringBuilder stringBuilder) { |
|
|
|
|
|
|
|
if (sort == OBJECT) { |
|
|
|
|
|
|
|
stringBuilder.append(valueBuffer, valueBegin - 1, valueEnd + 1); |
|
|
|
|
|
|
|
} else if (sort == INTERNAL) { |
|
|
|
|
|
|
|
stringBuilder.append('L'); |
|
|
|
|
|
|
|
stringBuilder.append(valueBuffer, valueBegin, valueEnd); |
|
|
|
|
|
|
|
stringBuilder.append(';'); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
stringBuilder.append(valueBuffer, valueBegin, valueEnd); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Direct conversion from classes to type descriptors,
|
|
|
|
|
|
|
|
// without intermediate Type objects
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the internal name of the given class. The internal name of a class is its fully |
|
|
|
|
|
|
|
* qualified name, as returned by Class.getName(), where '.' are replaced by '/'. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param clazz an object or array class. |
|
|
|
|
|
|
|
* @return the internal name of the given class. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static String getInternalName(final Class<?> clazz) { |
|
|
|
|
|
|
|
return clazz.getName().replace('.', '/'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the descriptor corresponding to the given class. |
|
|
|
* Returns the descriptor corresponding to the given class. |
|
|
|
* |
|
|
|
* |
|
|
|
@ -649,7 +526,7 @@ public class Type { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String getDescriptor(final Class<?> clazz) { |
|
|
|
public static String getDescriptor(final Class<?> clazz) { |
|
|
|
StringBuilder stringBuilder = new StringBuilder(); |
|
|
|
StringBuilder stringBuilder = new StringBuilder(); |
|
|
|
appendDescriptor(stringBuilder, clazz); |
|
|
|
appendDescriptor(clazz, stringBuilder); |
|
|
|
return stringBuilder.toString(); |
|
|
|
return stringBuilder.toString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -664,11 +541,29 @@ public class Type { |
|
|
|
stringBuilder.append('('); |
|
|
|
stringBuilder.append('('); |
|
|
|
Class<?>[] parameters = constructor.getParameterTypes(); |
|
|
|
Class<?>[] parameters = constructor.getParameterTypes(); |
|
|
|
for (int i = 0; i < parameters.length; ++i) { |
|
|
|
for (int i = 0; i < parameters.length; ++i) { |
|
|
|
appendDescriptor(stringBuilder, parameters[i]); |
|
|
|
appendDescriptor(parameters[i], stringBuilder); |
|
|
|
} |
|
|
|
} |
|
|
|
return stringBuilder.append(")V").toString(); |
|
|
|
return stringBuilder.append(")V").toString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the descriptor corresponding to the given argument and return types. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param returnType the return type of the method. |
|
|
|
|
|
|
|
* @param argumentTypes the argument types of the method. |
|
|
|
|
|
|
|
* @return the descriptor corresponding to the given argument and return types. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) { |
|
|
|
|
|
|
|
StringBuilder stringBuilder = new StringBuilder(); |
|
|
|
|
|
|
|
stringBuilder.append('('); |
|
|
|
|
|
|
|
for (int i = 0; i < argumentTypes.length; ++i) { |
|
|
|
|
|
|
|
argumentTypes[i].appendDescriptor(stringBuilder); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
stringBuilder.append(')'); |
|
|
|
|
|
|
|
returnType.appendDescriptor(stringBuilder); |
|
|
|
|
|
|
|
return stringBuilder.toString(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the descriptor corresponding to the given method. |
|
|
|
* Returns the descriptor corresponding to the given method. |
|
|
|
* |
|
|
|
* |
|
|
|
@ -680,20 +575,37 @@ public class Type { |
|
|
|
stringBuilder.append('('); |
|
|
|
stringBuilder.append('('); |
|
|
|
Class<?>[] parameters = method.getParameterTypes(); |
|
|
|
Class<?>[] parameters = method.getParameterTypes(); |
|
|
|
for (int i = 0; i < parameters.length; ++i) { |
|
|
|
for (int i = 0; i < parameters.length; ++i) { |
|
|
|
appendDescriptor(stringBuilder, parameters[i]); |
|
|
|
appendDescriptor(parameters[i], stringBuilder); |
|
|
|
} |
|
|
|
} |
|
|
|
stringBuilder.append(')'); |
|
|
|
stringBuilder.append(')'); |
|
|
|
appendDescriptor(stringBuilder, method.getReturnType()); |
|
|
|
appendDescriptor(method.getReturnType(), stringBuilder); |
|
|
|
return stringBuilder.toString(); |
|
|
|
return stringBuilder.toString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Appends the descriptor of the given class to the given string builder. |
|
|
|
* Appends the descriptor corresponding to this type to the given string buffer. |
|
|
|
* |
|
|
|
* |
|
|
|
* @param stringBuilder the string builder to which the descriptor must be appended. |
|
|
|
* @param stringBuilder the string builder to which the descriptor must be appended. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private void appendDescriptor(final StringBuilder stringBuilder) { |
|
|
|
|
|
|
|
if (sort == OBJECT) { |
|
|
|
|
|
|
|
stringBuilder.append(valueBuffer, valueBegin - 1, valueEnd + 1); |
|
|
|
|
|
|
|
} else if (sort == INTERNAL) { |
|
|
|
|
|
|
|
stringBuilder.append('L'); |
|
|
|
|
|
|
|
stringBuilder.append(valueBuffer, valueBegin, valueEnd); |
|
|
|
|
|
|
|
stringBuilder.append(';'); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
stringBuilder.append(valueBuffer, valueBegin, valueEnd); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Appends the descriptor of the given class to the given string builder. |
|
|
|
|
|
|
|
* |
|
|
|
* @param clazz the class whose descriptor must be computed. |
|
|
|
* @param clazz the class whose descriptor must be computed. |
|
|
|
|
|
|
|
* @param stringBuilder the string builder to which the descriptor must be appended. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private static void appendDescriptor(final StringBuilder stringBuilder, final Class<?> clazz) { |
|
|
|
private static void appendDescriptor(final Class<?> clazz, final StringBuilder stringBuilder) { |
|
|
|
Class<?> currentClass = clazz; |
|
|
|
Class<?> currentClass = clazz; |
|
|
|
while (currentClass.isArray()) { |
|
|
|
while (currentClass.isArray()) { |
|
|
|
stringBuilder.append('['); |
|
|
|
stringBuilder.append('['); |
|
|
|
@ -736,9 +648,34 @@ public class Type { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// Corresponding size and opcodes
|
|
|
|
// Methods to get the sort, dimension, size, and opcodes corresponding to a Type or descriptor.
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the sort of this type. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE}, {@link #SHORT}, {@link |
|
|
|
|
|
|
|
* #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY}, {@link #OBJECT} or |
|
|
|
|
|
|
|
* {@link #METHOD}. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public int getSort() { |
|
|
|
|
|
|
|
return sort == INTERNAL ? OBJECT : sort; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the number of dimensions of this array type. This method should only be used for an |
|
|
|
|
|
|
|
* array type. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return the number of dimensions of this array type. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public int getDimensions() { |
|
|
|
|
|
|
|
int numDimensions = 1; |
|
|
|
|
|
|
|
while (valueBuffer.charAt(valueBegin + numDimensions) == '[') { |
|
|
|
|
|
|
|
numDimensions++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return numDimensions; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the size of values of this type. This method must not be used for method types. |
|
|
|
* Returns the size of values of this type. This method must not be used for method types. |
|
|
|
* |
|
|
|
* |
|
|
|
@ -767,6 +704,60 @@ public class Type { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the size of the arguments and of the return value of methods of this type. This method |
|
|
|
|
|
|
|
* should only be used for method types. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return the size of the arguments of the method (plus one for the implicit this argument), |
|
|
|
|
|
|
|
* argumentsSize, and the size of its return value, returnSize, packed into a single int i = |
|
|
|
|
|
|
|
* {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code |
|
|
|
|
|
|
|
* i >> 2}, and returnSize to {@code i & 0x03}). |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public int getArgumentsAndReturnSizes() { |
|
|
|
|
|
|
|
return getArgumentsAndReturnSizes(getDescriptor()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Computes the size of the arguments and of the return value of a method. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param methodDescriptor a method descriptor. |
|
|
|
|
|
|
|
* @return the size of the arguments of the method (plus one for the implicit this argument), |
|
|
|
|
|
|
|
* argumentsSize, and the size of its return value, returnSize, packed into a single int i = |
|
|
|
|
|
|
|
* {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code |
|
|
|
|
|
|
|
* i >> 2}, and returnSize to {@code i & 0x03}). |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public static int getArgumentsAndReturnSizes(final String methodDescriptor) { |
|
|
|
|
|
|
|
int argumentsSize = 1; |
|
|
|
|
|
|
|
// Skip the first character, which is always a '('.
|
|
|
|
|
|
|
|
int currentOffset = 1; |
|
|
|
|
|
|
|
int currentChar = methodDescriptor.charAt(currentOffset); |
|
|
|
|
|
|
|
// Parse the argument types and compute their size, one at a each loop iteration.
|
|
|
|
|
|
|
|
while (currentChar != ')') { |
|
|
|
|
|
|
|
if (currentChar == 'J' || currentChar == 'D') { |
|
|
|
|
|
|
|
currentOffset++; |
|
|
|
|
|
|
|
argumentsSize += 2; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
while (methodDescriptor.charAt(currentOffset) == '[') { |
|
|
|
|
|
|
|
currentOffset++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (methodDescriptor.charAt(currentOffset++) == 'L') { |
|
|
|
|
|
|
|
while (methodDescriptor.charAt(currentOffset++) != ';') { |
|
|
|
|
|
|
|
// Skip the argument descriptor content.
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
argumentsSize += 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
currentChar = methodDescriptor.charAt(currentOffset); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
currentChar = methodDescriptor.charAt(currentOffset + 1); |
|
|
|
|
|
|
|
if (currentChar == 'V') { |
|
|
|
|
|
|
|
return argumentsSize << 2; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
int returnSize = (currentChar == 'J' || currentChar == 'D') ? 2 : 1; |
|
|
|
|
|
|
|
return argumentsSize << 2 | returnSize; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns a JVM instruction opcode adapted to this {@link Type}. This method must not be used for |
|
|
|
* Returns a JVM instruction opcode adapted to this {@link Type}. This method must not be used for |
|
|
|
* method types. |
|
|
|
* method types. |
|
|
|
@ -841,7 +832,7 @@ public class Type { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// Equals, hashCode and toString
|
|
|
|
// Equals, hashCode and toString.
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
|