2021-07-16 17:12:20 -05:00

935 lines
32 KiB
Java

/*
* @(#) $(JCGO)/goclsp/vm/java/lang/reflect/VMMethod.java --
* VM specific methods for Java "Method" implementation.
**
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
* Copyright (C) 2001-2009 Ivan Maidanski <ivmai@ivmaisoft.com>
* All rights reserved.
*/
/*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
**
* This software is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License (GPL) for more details.
**
* Linking this library statically or dynamically with other modules is
* making a combined work based on this library. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
**
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under
* terms of your choice, provided that you also meet, for each linked
* independent module, the terms and conditions of the license of that
* module. An independent module is a module which is not derived from
* or based on this library. If you modify this library, you may extend
* this exception to your version of the library, but you are not
* obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
package java.lang.reflect;
final class VMMethod /* hard-coded class name */
{ /* VM class */ /* used by VM classes only */
private static final int TYPECODE_BOOLEAN = 1;
private static final int TYPECODE_BYTE = 2;
private static final int TYPECODE_CHAR = 3;
private static final int TYPECODE_SHORT = 4;
private static final int TYPECODE_INT = 5;
private static final int TYPECODE_LONG = 6;
private static final int TYPECODE_FLOAT = 7;
private static final int TYPECODE_DOUBLE = 8;
private static final int TYPECODE_OBJECT = 9;
private static final Class[] EMPTY_TYPES = {};
static
{
if (!"".equals("")) /* hack */
{
getMethodDeclClass0X(null); /* hack */
getMethodSlot0X(null); /* hack */
getMethodByName0X(void.class, "", "", 0); /* hack */
getMethodBySlot0X(void.class, 0); /* hack */
}
}
private VMMethod() {}
static final int getModifiersInternal(Method method)
{
return method.modifiers;
}
static final Class getReturnType(Method method)
{
Class type = method.returnType;
if (type == null) /* hack */
throw new InternalError();
return type;
}
static final Class[] getParameterTypesInternal(Method method)
{
return method.parameterTypes;
}
static final Class[] getExceptionTypesInternal(Method method)
{
return method.exceptionTypes;
}
static final String getSignature(Method method)
{
return method.signature;
}
static final Object invoke(Method method, Object obj, Object[] args,
Class caller)
throws IllegalAccessException, InvocationTargetException
{
int modifiers = getModifiersInternal(method);
Class declaringClass = method.getDeclaringClass();
if ((modifiers & Modifier.STATIC) == 0)
{
if (obj == null)
throw new NullPointerException();
if (!declaringClass.isInstance(obj))
throw new IllegalArgumentException(
"not an instance of a method declaring class: " +
declaringClass.getName() + "." + method.getName());
}
if (caller != declaringClass && ((modifiers & Modifier.PUBLIC) == 0 ||
(declaringClass.getModifiers() & Modifier.PUBLIC) == 0) &&
caller != null && ((modifiers & Modifier.PRIVATE) != 0 ||
(((modifiers & Modifier.PROTECTED) == 0 ||
!declaringClass.isAssignableFrom(caller)) &&
!packageNameOf(declaringClass).equals(packageNameOf(caller)))))
throw new IllegalAccessException("method not accessible: " +
declaringClass.getName() + "." + method.getName());
Class[] parameterTypes = getParameterTypesInternal(method);
int argsCnt = parameterTypes.length;
if ((args != null ? args.length : 0) != argsCnt)
throw new IllegalArgumentException("method arguments number mismatch");
byte[] argsTypecodes = new byte[argsCnt];
int longArgsLen = 0;
int floatArgsLen = 0;
int doubleArgsLen = 0;
int objectArgsLen = 0;
for (int i = 0; i < argsCnt; i++)
{
Class type = parameterTypes[i];
int typecode;
if (type == double.class)
{
typecode = TYPECODE_DOUBLE;
doubleArgsLen++;
}
else if (type == float.class)
{
typecode = TYPECODE_FLOAT;
floatArgsLen++;
}
else if (type == long.class)
{
typecode = TYPECODE_LONG;
longArgsLen++;
}
else if (type == int.class)
typecode = TYPECODE_INT;
else if (type == short.class)
typecode = TYPECODE_SHORT;
else if (type == char.class)
typecode = TYPECODE_CHAR;
else if (type == byte.class)
typecode = TYPECODE_BYTE;
else if (type == boolean.class)
typecode = TYPECODE_BOOLEAN;
else
{
typecode = TYPECODE_OBJECT;
objectArgsLen++;
}
argsTypecodes[i] = (byte) typecode;
}
int intArgsLen = argsCnt - (longArgsLen + floatArgsLen + doubleArgsLen +
objectArgsLen);
int[] intArgs = new int[intArgsLen > 0 ? intArgsLen : 1];
long[] longArgs = new long[longArgsLen > 0 ? longArgsLen : 1];
float[] floatArgs = new float[floatArgsLen > 0 ? floatArgsLen : 1];
double[] doubleArgs = new double[doubleArgsLen > 0 ? doubleArgsLen : 1];
Object[] objectArgs = new Object[objectArgsLen];
intArgsLen = 0;
longArgsLen = 0;
floatArgsLen = 0;
doubleArgsLen = 0;
objectArgsLen = 0;
for (int i = 0; i < argsCnt; i++)
{
int typecode = argsTypecodes[i];
Object value = args[i];
switch (typecode)
{
case TYPECODE_BOOLEAN:
if (!(value instanceof Boolean))
throw new IllegalArgumentException("method argument type mismatch");
intArgs[intArgsLen++] = ((Boolean) value).booleanValue() ? 1 : 0;
break;
case TYPECODE_BYTE:
if (!(value instanceof Byte))
throw new IllegalArgumentException("method argument type mismatch");
intArgs[intArgsLen++] = ((Byte) value).intValue();
break;
case TYPECODE_CHAR:
if (!(value instanceof Character))
throw new IllegalArgumentException("method argument type mismatch");
intArgs[intArgsLen++] = ((Character) value).charValue();
break;
case TYPECODE_SHORT:
int intValue;
if (value instanceof Short)
intValue = ((Short) value).intValue();
else if (value instanceof Byte)
intValue = ((Byte) value).intValue();
else throw new IllegalArgumentException(
"method argument type mismatch");
intArgs[intArgsLen++] = intValue;
break;
case TYPECODE_INT:
intArgs[intArgsLen++] = unwrapIntValue(value);
break;
case TYPECODE_LONG:
long longValue;
if (value instanceof Long)
longValue = ((Long) value).longValue();
else longValue = unwrapIntValue(value);
longArgs[longArgsLen++] = longValue;
break;
case TYPECODE_FLOAT:
float floatValue;
if (value instanceof Float)
floatValue = ((Float) value).floatValue();
else if (value instanceof Long)
floatValue = ((Long) value).floatValue();
else floatValue = unwrapIntValue(value);
floatArgs[floatArgsLen++] = floatValue;
break;
case TYPECODE_DOUBLE:
double doubleValue;
if (value instanceof Double)
doubleValue = ((Double) value).doubleValue();
else if (value instanceof Float)
doubleValue = ((Float) value).doubleValue();
else if (value instanceof Long)
doubleValue = ((Long) value).doubleValue();
else doubleValue = unwrapIntValue(value);
doubleArgs[doubleArgsLen++] = doubleValue;
break;
default:
if (value != null && !parameterTypes[i].isInstance(value))
throw new IllegalArgumentException(
"method argument reference type mismatch");
objectArgs[objectArgsLen++] = value;
break;
}
}
int allowOverride = 0;
if ((modifiers & Modifier.STATIC) != 0)
{
obj = null;
VMAccessorJavaLang.initializeVMClass(declaringClass);
}
else if ((modifiers & (Modifier.PRIVATE | Modifier.FINAL)) == 0 &&
(declaringClass.getModifiers() & Modifier.FINAL) == 0)
allowOverride = 1;
Object value;
try
{
value = invokeNative0(declaringClass, obj, argsTypecodes, intArgs,
longArgs, floatArgs, doubleArgs, objectArgs, argsCnt, method.slot,
allowOverride);
}
catch (Error e)
{
throw e;
}
catch (Throwable e)
{
throw new InvocationTargetException(e);
}
Class type = getReturnType(method);
if (type == double.class)
value = new Double(doubleArgs[0]);
else if (type == float.class)
value = new Float(floatArgs[0]);
else if (type == long.class)
value = new Long(longArgs[0]);
else if (type == int.class)
value = new Integer(intArgs[0]);
else if (type == short.class)
value = new Short((short) intArgs[0]);
else if (type == char.class)
value = new Character((char) intArgs[0]);
else if (type == byte.class)
value = new Byte((byte) intArgs[0]);
else if (type == boolean.class)
value = intArgs[0] != 0 ? Boolean.TRUE : Boolean.FALSE;
return value;
}
static final Object invokeProxyHandler(InvocationHandler handler,
Proxy proxy, Class declaringClass, int[] intArgs, long[] longArgs,
float[] floatArgs, double[] doubleArgs, Object[] objectArgs, int slot,
int proxySlot)
throws Throwable
{
Method method = null;
Class returnType = void.class;
Class[] parameterTypes = EMPTY_TYPES;
int argsCnt = 0;
if (declaringClass != null)
{
Class[] methTypes = getMethodsTypes0(declaringClass)[slot];
if (methTypes != null)
{
byte[][] methodsDims;
byte[] dims = (methodsDims = getMethodsDims0(declaringClass)) != null ?
methodsDims[slot] : null;
argsCnt = methTypes.length - 1;
returnType = makeArrayClass(methTypes, dims, argsCnt);
if (argsCnt > 0)
parameterTypes = dims != null ? makeParameterTypes(argsCnt, methTypes,
dims) : copyTypes(methTypes, argsCnt);
}
Class[][] methodsThrows = getMethodsThrows0(declaringClass);
Class[] exceptionTypes;
short[] modifiers = getMethodsModifiers0(declaringClass);
String[] signatures = getMethodsSignature0(declaringClass);
method = new Method(declaringClass, getMethodsName0(declaringClass)[slot],
slot, returnType, parameterTypes, methodsThrows != null &&
(exceptionTypes = methodsThrows[slot]) != null ? exceptionTypes :
EMPTY_TYPES, modifiers != null ? modifiers[slot] & 0xffff :
declaringClass.isInterface() ? Modifier.PUBLIC |
Modifier.ABSTRACT : Modifier.PUBLIC, signatures != null ?
signatures[slot] : null);
}
Object[] args = null;
if (argsCnt > 0)
{
args = new Object[argsCnt];
int intArgsPos = 0;
int longArgsPos = 0;
int floatArgsPos = 0;
int doubleArgsPos = 0;
int objectArgsPos = 0;
for (int i = 0; i < argsCnt; i++)
{
Class type = parameterTypes[i];
args[i] =
type == double.class ? new Double(doubleArgs[doubleArgsPos++]) :
type == float.class ? new Float(floatArgs[floatArgsPos++]) :
type == long.class ? new Long(longArgs[longArgsPos++]) :
type == int.class ? new Integer(intArgs[intArgsPos++]) :
type == short.class ? new Short((short) intArgs[intArgsPos++]) :
type == char.class ? new Character((char) intArgs[intArgsPos++]) :
type == byte.class ? new Byte((byte) intArgs[intArgsPos++]) :
type == boolean.class ? (intArgs[intArgsPos++] != 0 ?
Boolean.TRUE : Boolean.FALSE) : objectArgs[objectArgsPos++];
}
}
Object value;
try
{
value = handler.invoke(proxy, method, args);
}
catch (Error e)
{
throw e;
}
catch (RuntimeException e)
{
throw e;
}
catch (Throwable e)
{
Class[] exceptionTypes = method.exceptionTypes;
if (proxySlot >= 0)
{
Class[][] methodsThrows = getMethodsThrows0(proxy.getClass());
if (methodsThrows == null ||
(exceptionTypes = methodsThrows[proxySlot]) == null)
exceptionTypes = EMPTY_TYPES;
}
int cnt = exceptionTypes.length;
if (cnt != 0)
{
Class excClass = e.getClass();
for (int i = 0; i < cnt; i++)
if (exceptionTypes[i].isAssignableFrom(excClass))
throw e;
}
throw new UndeclaredThrowableException(e);
}
if (returnType == void.class)
value = null;
else
{
Class wrapperClass = returnType;
if (returnType == double.class)
wrapperClass = Double.class;
else if (returnType == float.class)
wrapperClass = Float.class;
else if (returnType == long.class)
wrapperClass = Long.class;
else if (returnType == int.class)
wrapperClass = Integer.class;
else if (returnType == short.class)
wrapperClass = Short.class;
else if (returnType == char.class)
wrapperClass = Character.class;
else if (returnType == byte.class)
wrapperClass = Byte.class;
else if (returnType == boolean.class)
wrapperClass = Boolean.class;
if (value != null && !wrapperClass.isInstance(value))
throw new ClassCastException(value.getClass().getName());
if (wrapperClass != returnType)
{
if (value == null)
throw new NullPointerException();
if (returnType == double.class)
doubleArgs[0] = ((Double) value).doubleValue();
else if (returnType == float.class)
floatArgs[0] = ((Float) value).floatValue();
else if (returnType == long.class)
longArgs[0] = ((Long) value).longValue();
else intArgs[0] =
returnType == int.class ? ((Integer) value).intValue() :
returnType == short.class ? ((Short) value).intValue() :
returnType == char.class ? ((Character) value).charValue() :
returnType == byte.class ? ((Byte) value).intValue() :
((Boolean) value).booleanValue() ? 1 : 0;
value = null;
}
}
return value;
}
static final Constructor[] getDeclaredConstructors(Class klass,
boolean publicOnly)
{
Class[][] methodsTypes;
int count;
if (klass.isInterface() || klass.isPrimitive() || klass.isArray() ||
(methodsTypes = getMethodsTypes0(klass)) == null ||
(count = methodsTypes.length) == 0)
return new Constructor[0];
String[] names = getMethodsName0(klass);
short[] modifiers = getMethodsModifiers0(klass);
if (modifiers == null)
publicOnly = false;
int cnt = count;
if (names != null)
{
for (int i = 0; i < count; i++)
if ((names[i] != null && names[i].length() > 0) ||
(publicOnly && (modifiers[i] & Modifier.PUBLIC) == 0))
cnt--;
}
else
{
if (publicOnly)
for (int i = 0; i < count; i++)
if ((modifiers[i] & Modifier.PUBLIC) == 0)
cnt--;
}
Constructor[] constructors = new Constructor[cnt];
if (cnt > 0)
{
byte[][] methodsDims = getMethodsDims0(klass);
Class[][] methodsThrows = getMethodsThrows0(klass);
String[] signatures = getMethodsSignature0(klass);
cnt = 0;
for (int i = 0; i < count; i++)
if ((names == null || names[i] == null || names[i].length() == 0) &&
(!publicOnly || (modifiers[i] & Modifier.PUBLIC) != 0))
{
Class[] ctorTypes = methodsTypes[i];
Class[] parameterTypes = EMPTY_TYPES;
if (ctorTypes != null)
{
byte[] dims = methodsDims != null ? methodsDims[i] : null;
parameterTypes = ctorTypes;
if (dims != null)
parameterTypes = makeParameterTypes(ctorTypes.length, ctorTypes, dims);
}
Class[] exceptionTypes = methodsThrows != null ? methodsThrows[i] : null;
constructors[cnt++] = new Constructor(klass, i, parameterTypes,
exceptionTypes != null ? exceptionTypes :
EMPTY_TYPES, modifiers != null ?
modifiers[i] & 0xffff : Modifier.PUBLIC,
signatures != null ? signatures[i] : null);
}
}
return constructors;
}
static final Method[] getDeclaredMethods(Class klass, boolean publicOnly)
{
String[] names;
int count;
if (klass.isPrimitive() || klass.isArray() ||
(names = getMethodsName0(klass)) == null || (count = names.length) == 0)
return new Method[0];
short[] modifiers = getMethodsModifiers0(klass);
if (modifiers == null)
publicOnly = false;
int cnt = 0;
for (int i = 0; i < count; i++)
if (names[i] != null && names[i].length() != 0 &&
(!publicOnly || (modifiers[i] & Modifier.PUBLIC) != 0))
cnt++;
Method[] methods = new Method[cnt];
if (cnt != 0)
{
Class[][] methodsTypes = getMethodsTypes0(klass);
byte[][] methodsDims = getMethodsDims0(klass);
Class[][] methodsThrows = getMethodsThrows0(klass);
String[] signatures = getMethodsSignature0(klass);
int mods = klass.isInterface() ? Modifier.PUBLIC | Modifier.ABSTRACT :
Modifier.PUBLIC;
cnt = 0;
for (int i = 0; i < count; i++)
if (!publicOnly || (modifiers[i] & Modifier.PUBLIC) != 0)
{
String name = names[i];
if (name != null && name.length() != 0)
{
Class[] methTypes = methodsTypes[i];
Class returnType = void.class;
Class[] parameterTypes = EMPTY_TYPES;
if (methTypes != null)
{
byte[] dims = methodsDims != null ? methodsDims[i] : null;
int argsCnt = methTypes.length - 1;
returnType = makeArrayClass(methTypes, dims, argsCnt);
if (argsCnt > 0)
parameterTypes = dims != null ? makeParameterTypes(argsCnt, methTypes,
dims) : copyTypes(methTypes, argsCnt);
}
Class[] exceptionTypes = methodsThrows != null ?
methodsThrows[i] : null;
methods[cnt++] = new Method(klass, name, i, returnType, parameterTypes,
exceptionTypes != null ? exceptionTypes : EMPTY_TYPES,
modifiers != null ? modifiers[i] & 0xffff : mods,
signatures != null ? signatures[i] : null);
}
}
}
return methods;
}
static final Constructor getDeclaredConstructor(Class klass, Class[] types)
{ /* used by VM classes only */
Class[][] methodsTypes;
int count;
if (!klass.isInterface() && !klass.isPrimitive() && !klass.isArray() &&
(methodsTypes = getMethodsTypes0(klass)) != null &&
(count = methodsTypes.length) > 0)
{
String[] names = getMethodsName0(klass);
byte[][] methodsDims = null;
if (types != null)
methodsDims = getMethodsDims0(klass);
else types = EMPTY_TYPES;
for (int i = 0; i < count; i++)
if (names == null || names[i] == null || names[i].length() == 0)
{
Class[] ctorTypes;
if ((ctorTypes = methodsTypes[i]) == null)
ctorTypes = EMPTY_TYPES;
byte[] dims;
int argsCnt = ctorTypes.length;
if (types.length == argsCnt && matchMethodTypes(argsCnt, ctorTypes,
dims = methodsDims != null ? methodsDims[i] : null, types))
{
Class[] parameterTypes = ctorTypes;
if (dims != null)
parameterTypes = makeParameterTypes(argsCnt, ctorTypes, dims);
Class[][] methodsThrows = getMethodsThrows0(klass);
Class[] exceptionTypes = methodsThrows != null ?
methodsThrows[i] : null;
short[] modifiers;
String[] signatures;
return new Constructor(klass, i, parameterTypes,
exceptionTypes != null ? exceptionTypes : EMPTY_TYPES,
(modifiers = getMethodsModifiers0(klass)) != null ?
modifiers[i] & 0xffff : Modifier.PUBLIC,
(signatures = getMethodsSignature0(klass)) != null ?
signatures[i] : null);
}
}
}
return null;
}
static final Method getDeclaredMethod(Class klass, String methodName,
Class[] types)
{ /* used by VM classes only */
String[] names;
int count;
if (methodName.length() > 0 && !klass.isPrimitive() && !klass.isArray() &&
(names = getMethodsName0(klass)) != null && (count = names.length) > 0)
{
Class[][] methodsTypes = getMethodsTypes0(klass);
byte[][] methodsDims = getMethodsDims0(klass);
if (types == null)
types = EMPTY_TYPES;
for (int i = 0; i < count; i++)
if (methodName.equals(names[i]))
{
Class[] methTypes = methodsTypes[i];
int argsCnt = 0;
if (methTypes != null)
argsCnt = methTypes.length - 1;
byte[] dims;
if (types.length == argsCnt && matchMethodTypes(argsCnt, methTypes,
dims = methodsDims != null ? methodsDims[i] : null, types))
{
Class returnType = void.class;
Class[] parameterTypes = EMPTY_TYPES;
if (methTypes != null)
{
returnType = makeArrayClass(methTypes, dims, argsCnt);
if (argsCnt > 0)
parameterTypes = dims != null ? makeParameterTypes(argsCnt, methTypes,
dims) : copyTypes(methTypes, argsCnt);
}
Class[][] methodsThrows = getMethodsThrows0(klass);
Class[] exceptionTypes = methodsThrows != null ?
methodsThrows[i] : null;
short[] modifiers;
String[] signatures;
return new Method(klass, methodName, i, returnType, parameterTypes,
exceptionTypes != null ? exceptionTypes : EMPTY_TYPES,
(modifiers = getMethodsModifiers0(klass)) != null ?
modifiers[i] & 0xffff : klass.isInterface() ?
Modifier.PUBLIC | Modifier.ABSTRACT : Modifier.PUBLIC,
(signatures = getMethodsSignature0(klass)) != null ?
signatures[i] : null);
}
}
}
return null;
}
static final Class getMethodDeclClass0X(Object methodObj)
throws ClassCastException
{ /* called from native code */
Class declaringClass = methodObj instanceof Constructor ?
((Constructor) methodObj).getDeclaringClass() :
((Method) methodObj).getDeclaringClass();
VMAccessorJavaLang.initializeVMClass(declaringClass);
return declaringClass;
}
static final int getMethodSlot0X(Object methodObj)
{ /* called from native code */
return methodObj instanceof Constructor ? ((Constructor) methodObj).slot :
((Method) methodObj).slot;
}
static final Object getMethodByName0X(Class klass, String name,
String paramSig, int isStatic)
{ /* called from native code */
Class[] sigTypes;
if (klass.isPrimitive() || klass.isArray() || name.length() == 0 ||
(sigTypes = decodeMethodSig(paramSig, klass)) == null)
return null;
if (name.equals("<init>"))
return isStatic == 0 && !klass.isInterface() &&
sigTypes[sigTypes.length - 1] == void.class ?
getMethodByNameInner(klass, null, sigTypes, false) : null;
if (name.equals("<clinit>"))
{
if (isStatic != 0 && sigTypes.length == 1 && sigTypes[0] == void.class)
do
{
if (VMAccessorJavaLang.hasClassInitializerVMClass(klass))
return new Method(klass, "<clinit>", -1, void.class, EMPTY_TYPES,
EMPTY_TYPES, Modifier.STATIC | Modifier.SYNTHETIC, null);
} while ((klass = klass.getSuperclass()) != null);
return null;
}
return isStatic == 0 || !klass.isInterface() ?
getMethodByNameInner(klass, name, sigTypes, isStatic != 0) : null;
}
static final Object getMethodBySlot0X(Class klass, long slot)
{ /* called from native code */
Class[][] methodsTypes;
int count;
if (slot < 0 || klass.isPrimitive() || klass.isArray() ||
(methodsTypes = getMethodsTypes0(klass)) == null ||
(count = methodsTypes.length) <= slot)
return null;
String[] names = getMethodsName0(klass);
String name = null;
int intSlot = (int) slot;
if (names != null && (name = names[intSlot]) != null && name.length() == 0)
name = null;
Class[] methTypes = methodsTypes[intSlot];
Class returnType = void.class;
Class[] parameterTypes = EMPTY_TYPES;
if (methTypes != null)
{
int argsCnt = methTypes.length;
byte[][] methodsDims;
byte[] dims = (methodsDims = getMethodsDims0(klass)) != null ?
methodsDims[intSlot] : null;
if (name != null)
{
argsCnt--;
returnType = makeArrayClass(methTypes, dims, argsCnt);
}
if (argsCnt > 0)
parameterTypes = dims != null ? makeParameterTypes(argsCnt, methTypes,
dims) : name != null ? copyTypes(methTypes, argsCnt) :
methTypes;
}
Class[][] methodsThrows = getMethodsThrows0(klass);
Class[] exceptionTypes = methodsThrows != null ?
methodsThrows[intSlot] : null;
short[] modifiers = getMethodsModifiers0(klass);
String[] signatures = getMethodsSignature0(klass);
String signature = signatures != null ? signatures[intSlot] : null;
if (exceptionTypes == null)
exceptionTypes = EMPTY_TYPES;
if (name != null)
return new Method(klass, name, intSlot, returnType, parameterTypes,
exceptionTypes, modifiers != null ? modifiers[intSlot] & 0xffff :
klass.isInterface() ? Modifier.PUBLIC | Modifier.ABSTRACT :
Modifier.PUBLIC, signature);
return new Constructor(klass, intSlot, parameterTypes, exceptionTypes,
modifiers != null ? modifiers[intSlot] & 0xffff : Modifier.PUBLIC,
signature);
}
private static Object getMethodByNameInner(Class klass, String name,
Class[] sigTypes, boolean isStatic)
{
int argsCnt = sigTypes.length - 1;
Class returnType = sigTypes[argsCnt];
Class aclass = klass;
Object method = null;
do
{
Class[][] methodsTypes;
String[] names;
int count;
if ((methodsTypes = getMethodsTypes0(aclass)) != null &&
(count = methodsTypes.length) != 0 &&
((names = getMethodsName0(aclass)) != null || name == null))
{
byte[][] methodsDims = getMethodsDims0(aclass);
short[] modifiers = getMethodsModifiers0(aclass);
Class[] methTypes;
int mods = aclass.isInterface() ? Modifier.PUBLIC | Modifier.ABSTRACT :
Modifier.PUBLIC;
for (int i = 0; i < count; i++)
if ((name != null ? name.equals(names[i]) :
names == null || names[i] == null || names[i].length() == 0) &&
((methTypes = methodsTypes[i]) != null ? methTypes.length -
(name != null ? 1 : 0) == argsCnt : argsCnt == 0) && (name != null &&
methTypes != null ? makeArrayClass(methTypes, methodsDims != null ?
methodsDims[i] : null, argsCnt) : void.class) == returnType &&
(((modifiers != null ? (mods = modifiers[i] & 0xffff) :
mods) & Modifier.STATIC) != 0) == isStatic)
{
byte[] dims = methodsDims != null && argsCnt > 0 ?
methodsDims[i] : null;
if (matchMethodTypes(argsCnt, methTypes, dims, sigTypes))
{
Class[] parameterTypes = EMPTY_TYPES;
if (argsCnt > 0 && methTypes != null)
parameterTypes = dims != null || name != null ?
copyTypes(sigTypes, argsCnt) : methTypes;
Class[][] methodsThrows;
Class[] exceptionTypes;
if ((methodsThrows = getMethodsThrows0(aclass)) == null ||
(exceptionTypes = methodsThrows[i]) == null)
exceptionTypes = EMPTY_TYPES;
String[] signatures = getMethodsSignature0(aclass);
String signature = signatures != null ? signatures[i] : null;
Object m;
if (name != null)
m = new Method(aclass, names[i], i, returnType, parameterTypes,
exceptionTypes, mods, signature);
else m = new Constructor(aclass, i, parameterTypes, exceptionTypes,
mods, signature);
if (aclass == klass ||
(mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0 ||
((mods & Modifier.PRIVATE) == 0 &&
packageNameOf(aclass).equals(packageNameOf(klass))))
return m;
if (method == null)
method = m;
break;
}
}
}
if (name == null)
break;
if (!isStatic)
{
Class[] interfaces = VMAccessorJavaLang.getInterfacesInnerVMClass(aclass);
int len = interfaces.length;
for (int i = 0; i < len; i++)
{
Object m = getMethodByNameInner(interfaces[i], name, sigTypes, false);
if (m != null)
return m;
}
}
aclass = aclass.getSuperclass();
} while (aclass != null);
return method;
}
private static Class[] decodeMethodSig(String paramSig, Class klass)
{
int len = paramSig.length();
if (len <= 1 || paramSig.charAt(0) != '(')
return null;
int pos = 1;
int count = 0;
char ch;
while ((ch = paramSig.charAt(pos)) != ')')
{
if (ch != '[')
{
if (ch == 'L' && (pos = paramSig.indexOf(';', pos + 1)) < 0)
return null;
count++;
}
if (++pos >= len)
return null;
}
Class[] sigTypes = new Class[count + 1];
pos = 1;
for (int i = 0; i < count; i++)
{
int next = pos;
while ((ch = paramSig.charAt(next)) == '[')
next++;
next = (ch == 'L' ? paramSig.indexOf(';', next + 1) : next) + 1;
Class type = VMAccessorJavaLang.classForSigVMClass(paramSig.substring(pos,
next), klass);
if (type == null || type == void.class)
return null;
sigTypes[i] = type;
pos = next;
}
return (sigTypes[count] = VMAccessorJavaLang.classForSigVMClass(
paramSig.substring(pos + 1), klass)) != null ? sigTypes : null;
}
private static int unwrapIntValue(Object value)
{
int intValue;
if (value instanceof Integer)
intValue = ((Integer) value).intValue();
else if (value instanceof Short)
intValue = ((Short) value).intValue();
else if (value instanceof Character)
intValue = ((Character) value).charValue();
else if (value instanceof Byte)
intValue = ((Byte) value).intValue();
else throw new IllegalArgumentException(
"method argument type mismatch");
return intValue;
}
private static String packageNameOf(Class aclass)
{
String name = aclass.getName();
int lastInd = name.lastIndexOf('.');
return lastInd > 0 ? name.substring(0, lastInd) : "";
}
private static Class[] copyTypes(Class[] types, int count)
{
Class[] destTypes = new Class[count];
for (int i = 0; i < count; i++) /* hack */
destTypes[i] = types[i];
return destTypes;
}
private static boolean matchMethodTypes(int argsCnt, Class[] methTypes,
byte[] dims, Class[] types)
{
for (int i = 0; i < argsCnt; i++)
if (makeArrayClass(methTypes, dims, i) != types[i])
return false;
return true;
}
private static Class[] makeParameterTypes(int argsCnt, Class[] methTypes,
byte[] dims)
{
Class[] parameterTypes = new Class[argsCnt];
for (int i = 0; i < argsCnt; i++)
parameterTypes[i] = VMAccessorJavaLang.arrayClassOfVMClass(methTypes[i],
dims[i] & 0xff);
return parameterTypes;
}
private static Class makeArrayClass(Class[] types, byte[] dims, int index)
{
return dims != null ? VMAccessorJavaLang.arrayClassOfVMClass(types[index],
dims[index] & 0xff) : types[index];
}
private static native String[] getMethodsName0(
Class klass); /* JVM-core */ /* const data */
private static native byte[][] getMethodsDims0(
Class klass); /* JVM-core */ /* const data of const data */
private static native Class[][] getMethodsThrows0(
Class klass); /* JVM-core */ /* const data of const data */
private static native short[] getMethodsModifiers0(
Class klass); /* JVM-core */ /* const data */
private static native String[] getMethodsSignature0(
Class klass); /* JVM-core */ /* const data */
private static native Class[][] getMethodsTypes0(
Class klass); /* JVM-core */ /* const data of const data */
private static native Object invokeNative0(Class declaringClass, Object obj,
byte[] argsTypecodes, int[] intArgs, long[] longArgs, float[] floatArgs,
double[] doubleArgs, Object[] objectArgs, int argsCnt, int slot,
int allowOverride)
throws Throwable; /* JVM-core */
}