mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
741 lines
24 KiB
Java
741 lines
24 KiB
Java
![]() |
/*
|
||
|
* @(#) $(JCGO)/goclsp/vm/java/lang/reflect/VMField.java --
|
||
|
* VM specific methods for Java "Field" implementation.
|
||
|
**
|
||
|
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
|
||
|
* Copyright (C) 2001-2012 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 VMField /* 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;
|
||
|
|
||
|
static
|
||
|
{
|
||
|
if (!"".equals("")) /* hack */
|
||
|
{
|
||
|
getStaticFieldClass0X(null); /* hack */
|
||
|
getSlotOfField0X(null); /* hack */
|
||
|
getFieldByName0X(void.class, "", "", 0); /* hack */
|
||
|
getFieldBySlot0X(void.class, 0); /* hack */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private VMField() {}
|
||
|
|
||
|
static final int getModifiersInternal(Field field)
|
||
|
{
|
||
|
return field.modifiers;
|
||
|
}
|
||
|
|
||
|
static final Class getType(Field field)
|
||
|
{
|
||
|
Class type = field.type;
|
||
|
if (type == null) /* hack */
|
||
|
throw new InternalError();
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
static final String getSignature(Field field)
|
||
|
{
|
||
|
return field.signature;
|
||
|
}
|
||
|
|
||
|
static final Object get(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
Class type = getType(field);
|
||
|
int mods = getModifiersInternal(field);
|
||
|
if (type == double.class)
|
||
|
return new Double(getDouble0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
mods));
|
||
|
if (type == float.class)
|
||
|
return new Float(getFloat0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
mods));
|
||
|
if (type == long.class)
|
||
|
return new Long(getLong0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
mods));
|
||
|
if (type == int.class)
|
||
|
return new Integer(getInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
mods, TYPECODE_INT));
|
||
|
if (type == short.class)
|
||
|
return new Short((short) getInt0(fieldObjectOrClass(field, obj),
|
||
|
field.slot, mods, TYPECODE_SHORT));
|
||
|
if (type == char.class)
|
||
|
return new Character((char) getInt0(fieldObjectOrClass(field, obj),
|
||
|
field.slot, mods, TYPECODE_CHAR));
|
||
|
if (type == byte.class)
|
||
|
return new Byte((byte) getInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
mods, TYPECODE_BYTE));
|
||
|
if (type == boolean.class)
|
||
|
return getInt0(fieldObjectOrClass(field, obj), field.slot, mods,
|
||
|
TYPECODE_BOOLEAN) != 0 ? Boolean.TRUE : Boolean.FALSE;
|
||
|
return get0(fieldObjectOrClass(field, obj), field.slot, mods);
|
||
|
}
|
||
|
|
||
|
static final boolean getBoolean(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
if (getType(field) != boolean.class)
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
return getInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), TYPECODE_BOOLEAN) != 0;
|
||
|
}
|
||
|
|
||
|
static final byte getByte(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
if (getType(field) != byte.class)
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
return (byte) getInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), TYPECODE_BYTE);
|
||
|
}
|
||
|
|
||
|
static final char getChar(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
if (getType(field) != char.class)
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
return (char) getInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), TYPECODE_CHAR);
|
||
|
}
|
||
|
|
||
|
static final short getShort(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
Class type = getType(field);
|
||
|
int typecode = TYPECODE_SHORT;
|
||
|
if (type != short.class)
|
||
|
{
|
||
|
if (type == byte.class)
|
||
|
typecode = TYPECODE_BYTE;
|
||
|
else throw new IllegalArgumentException("field type mismatch");
|
||
|
}
|
||
|
return (short) getInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), typecode);
|
||
|
}
|
||
|
|
||
|
static final int getInt(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
return getIntInner(field, obj);
|
||
|
}
|
||
|
|
||
|
static final long getLong(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
if (getType(field) == long.class)
|
||
|
return getLong0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field));
|
||
|
return getIntInner(field, obj);
|
||
|
}
|
||
|
|
||
|
static final float getFloat(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
Class type = getType(field);
|
||
|
if (type == float.class)
|
||
|
return getFloat0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field));
|
||
|
if (type == long.class)
|
||
|
return getLong0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field));
|
||
|
return getIntInner(field, obj);
|
||
|
}
|
||
|
|
||
|
static final double getDouble(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
Class type = getType(field);
|
||
|
if (type == double.class)
|
||
|
return getDouble0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field));
|
||
|
if (type == float.class)
|
||
|
return getFloat0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field));
|
||
|
if (type == long.class)
|
||
|
return getLong0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field));
|
||
|
return getIntInner(field, obj);
|
||
|
}
|
||
|
|
||
|
static final void set(Field field, Object obj, Object value, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowWrite(field, obj, caller);
|
||
|
Class type = getType(field);
|
||
|
int mods = getModifiersInternal(field);
|
||
|
if (type == boolean.class)
|
||
|
{
|
||
|
if (!(value instanceof Boolean))
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
int intValue = ((Boolean) value).booleanValue() ? 1 : 0;
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot, mods, TYPECODE_BOOLEAN,
|
||
|
intValue);
|
||
|
}
|
||
|
else if (type == byte.class)
|
||
|
{
|
||
|
if (!(value instanceof Byte))
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
int intValue = ((Byte) value).intValue();
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot, mods, TYPECODE_BYTE,
|
||
|
intValue);
|
||
|
}
|
||
|
else if (type == char.class)
|
||
|
{
|
||
|
if (!(value instanceof Character))
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
int intValue = ((Character) value).charValue();
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot, mods, TYPECODE_CHAR,
|
||
|
intValue);
|
||
|
}
|
||
|
else if (type == short.class)
|
||
|
{
|
||
|
int intValue;
|
||
|
if (value instanceof Short)
|
||
|
intValue = ((Short) value).intValue();
|
||
|
else if (value instanceof Byte)
|
||
|
intValue = ((Byte) value).intValue();
|
||
|
else throw new IllegalArgumentException("field type mismatch");
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot, mods,
|
||
|
TYPECODE_SHORT, intValue);
|
||
|
}
|
||
|
else if (type == int.class)
|
||
|
{
|
||
|
int intValue = unwrapIntValue(value);
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot, mods, TYPECODE_INT,
|
||
|
intValue);
|
||
|
}
|
||
|
else if (type == long.class)
|
||
|
{
|
||
|
long longValue;
|
||
|
if (value instanceof Long)
|
||
|
longValue = ((Long) value).longValue();
|
||
|
else longValue = unwrapIntValue(value);
|
||
|
setLong0(fieldObjectOrClass(field, obj), longValue, field.slot, mods);
|
||
|
}
|
||
|
else if (type == float.class)
|
||
|
setFloat0(fieldObjectOrClass(field, obj), value instanceof Float ||
|
||
|
value instanceof Long ? ((Number) value).floatValue() :
|
||
|
unwrapIntValue(value), field.slot, mods);
|
||
|
else if (type == double.class)
|
||
|
setDouble0(fieldObjectOrClass(field, obj),
|
||
|
value instanceof Double || value instanceof Float ||
|
||
|
value instanceof Long ? ((Number) value).doubleValue() :
|
||
|
unwrapIntValue(value), field.slot, mods);
|
||
|
else
|
||
|
{
|
||
|
if (value != null && !type.isInstance(value))
|
||
|
throw new IllegalArgumentException(
|
||
|
"field reference type mismatch");
|
||
|
set0(fieldObjectOrClass(field, obj), value, field.slot, mods);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static final void setBoolean(Field field, Object obj, boolean value,
|
||
|
Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowWrite(field, obj, caller);
|
||
|
if (getType(field) != boolean.class)
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), TYPECODE_BOOLEAN, value ? 1 : 0);
|
||
|
}
|
||
|
|
||
|
static final void setByte(Field field, Object obj, byte value, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowWrite(field, obj, caller);
|
||
|
Class type = getType(field);
|
||
|
if (type == byte.class)
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), TYPECODE_BYTE, value);
|
||
|
else if (type == short.class)
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), TYPECODE_SHORT, value);
|
||
|
else setIntInner(field, obj, value);
|
||
|
}
|
||
|
|
||
|
static final void setChar(Field field, Object obj, char value, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowWrite(field, obj, caller);
|
||
|
if (getType(field) == char.class)
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), TYPECODE_CHAR, value);
|
||
|
else setIntInner(field, obj, value);
|
||
|
}
|
||
|
|
||
|
static final void setShort(Field field, Object obj, short value,
|
||
|
Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowWrite(field, obj, caller);
|
||
|
if (getType(field) == short.class)
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), TYPECODE_SHORT, value);
|
||
|
else setIntInner(field, obj, value);
|
||
|
}
|
||
|
|
||
|
static final void setInt(Field field, Object obj, int value, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowWrite(field, obj, caller);
|
||
|
setIntInner(field, obj, value);
|
||
|
}
|
||
|
|
||
|
static final void setLong(Field field, Object obj, long value, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowWrite(field, obj, caller);
|
||
|
Class type = getType(field);
|
||
|
int mods = getModifiersInternal(field);
|
||
|
if (type == long.class)
|
||
|
setLong0(fieldObjectOrClass(field, obj), value, field.slot, mods);
|
||
|
else if (type == float.class)
|
||
|
setFloat0(fieldObjectOrClass(field, obj), value, field.slot, mods);
|
||
|
else
|
||
|
{
|
||
|
if (type != double.class)
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
setDouble0(fieldObjectOrClass(field, obj), value, field.slot, mods);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static final void setFloat(Field field, Object obj, float value,
|
||
|
Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowWrite(field, obj, caller);
|
||
|
Class type = getType(field);
|
||
|
int mods = getModifiersInternal(field);
|
||
|
if (type == float.class)
|
||
|
setFloat0(fieldObjectOrClass(field, obj), value, field.slot, mods);
|
||
|
else
|
||
|
{
|
||
|
if (type != double.class)
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
setDouble0(fieldObjectOrClass(field, obj), value, field.slot, mods);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static final void setDouble(Field field, Object obj, double value,
|
||
|
Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowWrite(field, obj, caller);
|
||
|
if (getType(field) != double.class)
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
setDouble0(fieldObjectOrClass(field, obj), value, field.slot,
|
||
|
getModifiersInternal(field));
|
||
|
}
|
||
|
|
||
|
static final Field createNonFinalAccessible(Field field)
|
||
|
{
|
||
|
field = new Field(field.getDeclaringClass(), field.getName(), field.slot,
|
||
|
getType(field), getModifiersInternal(field) & ~Modifier.FINAL,
|
||
|
getSignature(field));
|
||
|
field.setAccessible(true);
|
||
|
return field;
|
||
|
}
|
||
|
|
||
|
static final long objectFieldOffset(Field field)
|
||
|
{
|
||
|
Class aclass = null;
|
||
|
if ((getModifiersInternal(field) & Modifier.STATIC) != 0)
|
||
|
{
|
||
|
aclass = field.getDeclaringClass();
|
||
|
VMAccessorJavaLang.initializeVMClass(aclass);
|
||
|
}
|
||
|
return objectFieldOffset0(aclass, field.slot);
|
||
|
}
|
||
|
|
||
|
static final Field[] getDeclaredFields(Class klass, boolean publicOnly)
|
||
|
{
|
||
|
String[] names;
|
||
|
int count;
|
||
|
if (klass.isPrimitive() || klass.isArray() ||
|
||
|
(names = getFieldsName0(klass)) == null || (count = names.length) == 0)
|
||
|
return new Field[0];
|
||
|
short[] modifiers = getFieldsModifiers0(klass);
|
||
|
int mods;
|
||
|
int cnt = count;
|
||
|
if (modifiers == null && klass.isInterface())
|
||
|
{
|
||
|
publicOnly = false;
|
||
|
mods = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mods = 0;
|
||
|
if (publicOnly)
|
||
|
{
|
||
|
cnt = 0;
|
||
|
if (modifiers != null)
|
||
|
for (int i = 0; i < count; i++)
|
||
|
if ((modifiers[i] & Modifier.PUBLIC) != 0)
|
||
|
cnt++;
|
||
|
}
|
||
|
}
|
||
|
Field[] fields = new Field[cnt];
|
||
|
if (cnt > 0)
|
||
|
{
|
||
|
int[] slots = getFieldsSlot0(klass);
|
||
|
Class[] types = getFieldsType0(klass);
|
||
|
byte[] dims = getFieldsDims0(klass);
|
||
|
String[] signatures = getFieldsSignature0(klass);
|
||
|
cnt = 0;
|
||
|
for (int i = 0; i < count; i++)
|
||
|
if (!publicOnly || (modifiers[i] & Modifier.PUBLIC) != 0)
|
||
|
fields[cnt++] = new Field(klass, names[i], slots != null ? slots[i] : i,
|
||
|
makeArrayClass(types, dims, i),
|
||
|
modifiers != null ? modifiers[i] & 0xffff : mods,
|
||
|
signatures != null ? signatures[i] : null);
|
||
|
}
|
||
|
return fields;
|
||
|
}
|
||
|
|
||
|
static final Field getDeclaredField(Class klass, String fieldName)
|
||
|
{ /* used by VM classes only */
|
||
|
String[] names;
|
||
|
if (!klass.isPrimitive() && !klass.isArray() &&
|
||
|
(names = getFieldsName0(klass)) != null)
|
||
|
{
|
||
|
short[] modifiers;
|
||
|
int[] slots;
|
||
|
String[] signatures;
|
||
|
int count = names.length;
|
||
|
for (int i = 0; i < count; i++)
|
||
|
if (fieldName.equals(names[i]))
|
||
|
return new Field(klass, fieldName,
|
||
|
(slots = getFieldsSlot0(klass)) != null ? slots[i] : i,
|
||
|
makeArrayClass(getFieldsType0(klass), getFieldsDims0(klass), i),
|
||
|
(modifiers = getFieldsModifiers0(klass)) != null ?
|
||
|
modifiers[i] & 0xffff : klass.isInterface() ?
|
||
|
Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL : 0,
|
||
|
(signatures = getFieldsSignature0(klass)) != null ?
|
||
|
signatures[i] : null);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
static final Class getStaticFieldClass0X(Object fieldObj)
|
||
|
{ /* called from native code */
|
||
|
Field field = (Field) fieldObj;
|
||
|
return (getModifiersInternal(field) & Modifier.STATIC) != 0 ?
|
||
|
field.getDeclaringClass() : null;
|
||
|
}
|
||
|
|
||
|
static final int getSlotOfField0X(Object fieldObj)
|
||
|
throws ClassCastException
|
||
|
{ /* called from native code */
|
||
|
Field field = (Field) fieldObj;
|
||
|
VMAccessorJavaLang.initializeVMClass(field.getDeclaringClass());
|
||
|
return field.slot;
|
||
|
}
|
||
|
|
||
|
static final Object getFieldByName0X(Class klass, String name,
|
||
|
String typeSig, int isStatic)
|
||
|
{ /* called from native code */
|
||
|
Class type = null;
|
||
|
return !klass.isPrimitive() && !klass.isArray() && (typeSig == null ||
|
||
|
(type = VMAccessorJavaLang.classForSigVMClass(typeSig,
|
||
|
klass)) != null) ? getFieldByNameInner(klass, name, type,
|
||
|
isStatic != 0) : null;
|
||
|
}
|
||
|
|
||
|
static final Object getFieldBySlot0X(Class klass, long slot)
|
||
|
{ /* called from native code */
|
||
|
String[] names;
|
||
|
int intSlot = (int) slot;
|
||
|
int count;
|
||
|
if (intSlot >= 0 && !klass.isPrimitive() && !klass.isArray() &&
|
||
|
(long) intSlot == slot && (names = getFieldsName0(klass)) != null &&
|
||
|
(count = names.length) != 0)
|
||
|
{
|
||
|
int[] slots = getFieldsSlot0(klass);
|
||
|
for (int i = 0; i < count; i++)
|
||
|
if ((slots != null ? slots[i] : i) == intSlot)
|
||
|
{
|
||
|
Class[] types = getFieldsType0(klass);
|
||
|
byte[] dims = getFieldsDims0(klass);
|
||
|
short[] modifiers = getFieldsModifiers0(klass);
|
||
|
String[] signatures = getFieldsSignature0(klass);
|
||
|
return new Field(klass, names[i], intSlot, makeArrayClass(types,
|
||
|
dims, i), modifiers != null ? modifiers[i] & 0xffff :
|
||
|
klass.isInterface() ? Modifier.PUBLIC | Modifier.STATIC |
|
||
|
Modifier.FINAL : 0, signatures != null ? signatures[i] : null);
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private static void checkAllowGet(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
int modifiers = getModifiersInternal(field);
|
||
|
Class declaringClass = field.getDeclaringClass();
|
||
|
if ((modifiers & Modifier.STATIC) == 0)
|
||
|
{
|
||
|
if (obj == null)
|
||
|
throw new NullPointerException();
|
||
|
if (!declaringClass.isInstance(obj))
|
||
|
throw new IllegalArgumentException(
|
||
|
"not an instance of a field declaring class: " +
|
||
|
declaringClass.getName());
|
||
|
}
|
||
|
if ((modifiers & Modifier.PUBLIC) == 0 && caller != declaringClass &&
|
||
|
caller != null && ((modifiers & Modifier.PRIVATE) != 0 ||
|
||
|
(((modifiers & Modifier.PROTECTED) == 0 ||
|
||
|
!declaringClass.isAssignableFrom(caller)) &&
|
||
|
!packageNameOf(declaringClass).equals(packageNameOf(caller)))))
|
||
|
throw new IllegalAccessException("field not accessible: " +
|
||
|
declaringClass.getName() + "." + field.getName());
|
||
|
}
|
||
|
|
||
|
private static void checkAllowWrite(Field field, Object obj, Class caller)
|
||
|
throws IllegalAccessException
|
||
|
{
|
||
|
checkAllowGet(field, obj, caller);
|
||
|
if ((getModifiersInternal(field) & Modifier.FINAL) != 0 &&
|
||
|
!field.isAccessible())
|
||
|
throw new IllegalAccessException("cannot set final field: " +
|
||
|
field.getDeclaringClass().getName() + "." + field.getName());
|
||
|
}
|
||
|
|
||
|
private static Object fieldObjectOrClass(Field field, Object obj)
|
||
|
{
|
||
|
if ((getModifiersInternal(field) & Modifier.STATIC) == 0)
|
||
|
return obj;
|
||
|
Class declaringClass = field.getDeclaringClass();
|
||
|
VMAccessorJavaLang.initializeVMClass(declaringClass);
|
||
|
return declaringClass;
|
||
|
}
|
||
|
|
||
|
private static int getIntInner(Field field, Object obj)
|
||
|
{
|
||
|
Class type = getType(field);
|
||
|
int typecode = TYPECODE_INT;
|
||
|
if (type != int.class)
|
||
|
{
|
||
|
if (type == short.class)
|
||
|
typecode = TYPECODE_SHORT;
|
||
|
else if (type == char.class)
|
||
|
typecode = TYPECODE_CHAR;
|
||
|
else if (type == byte.class)
|
||
|
typecode = TYPECODE_BYTE;
|
||
|
else throw new IllegalArgumentException("field type mismatch");
|
||
|
}
|
||
|
return getInt0(fieldObjectOrClass(field, obj), field.slot,
|
||
|
getModifiersInternal(field), typecode);
|
||
|
}
|
||
|
|
||
|
private static void setIntInner(Field field, Object obj, int value)
|
||
|
{
|
||
|
Class type = getType(field);
|
||
|
int mods = getModifiersInternal(field);
|
||
|
if (type == int.class)
|
||
|
setInt0(fieldObjectOrClass(field, obj), field.slot, mods, TYPECODE_INT,
|
||
|
value);
|
||
|
else if (type == long.class)
|
||
|
setLong0(fieldObjectOrClass(field, obj), value, field.slot, mods);
|
||
|
else if (type == float.class)
|
||
|
setFloat0(fieldObjectOrClass(field, obj), value, field.slot, mods);
|
||
|
else
|
||
|
{
|
||
|
if (type != double.class)
|
||
|
throw new IllegalArgumentException("field type mismatch");
|
||
|
setDouble0(fieldObjectOrClass(field, obj), value, field.slot, mods);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static String packageNameOf(Class aclass)
|
||
|
{
|
||
|
String name = aclass.getName();
|
||
|
int lastInd = name.lastIndexOf('.');
|
||
|
return lastInd > 0 ? name.substring(0, lastInd) : "";
|
||
|
}
|
||
|
|
||
|
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("field type mismatch");
|
||
|
return intValue;
|
||
|
}
|
||
|
|
||
|
private static Field getFieldByNameInner(Class klass, String name,
|
||
|
Class type, boolean isStatic)
|
||
|
{
|
||
|
Class aclass = klass;
|
||
|
Field field = null;
|
||
|
do
|
||
|
{
|
||
|
String[] names = getFieldsName0(aclass);
|
||
|
int count;
|
||
|
if (names != null && (count = names.length) != 0)
|
||
|
{
|
||
|
Class[] types = getFieldsType0(aclass);
|
||
|
byte[] dims = getFieldsDims0(aclass);
|
||
|
short[] modifiers = getFieldsModifiers0(aclass);
|
||
|
int mods = aclass.isInterface() ?
|
||
|
Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL : 0;
|
||
|
for (int i = 0; i < count; i++)
|
||
|
if (name.equals(names[i]))
|
||
|
{
|
||
|
if (modifiers != null)
|
||
|
mods = modifiers[i] & 0xffff;
|
||
|
if (((mods & Modifier.STATIC) != 0) == isStatic)
|
||
|
{
|
||
|
Class fieldType = makeArrayClass(types, dims, i);
|
||
|
if (type == null || type == fieldType)
|
||
|
{
|
||
|
int[] slots = getFieldsSlot0(aclass);
|
||
|
String[] signatures = getFieldsSignature0(klass);
|
||
|
Field f = new Field(aclass, names[i], slots != null ? slots[i] : i,
|
||
|
fieldType, mods, signatures != null ? signatures[i] :
|
||
|
null);
|
||
|
if (aclass == klass ||
|
||
|
(mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0 ||
|
||
|
((mods & Modifier.PRIVATE) == 0 &&
|
||
|
packageNameOf(aclass).equals(packageNameOf(klass))))
|
||
|
return f;
|
||
|
if (field == null)
|
||
|
field = f;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (isStatic)
|
||
|
{
|
||
|
Class[] interfaces = VMAccessorJavaLang.getInterfacesInnerVMClass(aclass);
|
||
|
int len = interfaces.length;
|
||
|
for (int i = 0; i < len; i++)
|
||
|
{
|
||
|
Field f = getFieldByNameInner(interfaces[i], name, type, true);
|
||
|
if (f != null)
|
||
|
return f;
|
||
|
}
|
||
|
}
|
||
|
aclass = aclass.getSuperclass();
|
||
|
} while (aclass != null);
|
||
|
return field;
|
||
|
}
|
||
|
|
||
|
private static Class makeArrayClass(Class[] types, byte[] dims, int i)
|
||
|
{
|
||
|
return dims != null ? VMAccessorJavaLang.arrayClassOfVMClass(types[i],
|
||
|
dims[i] & 0xff) : types[i];
|
||
|
}
|
||
|
|
||
|
private static native String[] getFieldsName0(
|
||
|
Class klass); /* JVM-core */ /* const data */
|
||
|
|
||
|
private static native int[] getFieldsSlot0(
|
||
|
Class klass); /* JVM-core */ /* const data */
|
||
|
|
||
|
private static native Class[] getFieldsType0(
|
||
|
Class klass); /* JVM-core */ /* const data */
|
||
|
|
||
|
private static native byte[] getFieldsDims0(
|
||
|
Class klass); /* JVM-core */ /* const data */
|
||
|
|
||
|
private static native short[] getFieldsModifiers0(
|
||
|
Class klass); /* JVM-core */ /* const data */
|
||
|
|
||
|
private static native String[] getFieldsSignature0(
|
||
|
Class klass); /* JVM-core */ /* const data */
|
||
|
|
||
|
private static native int getInt0(Object objOrClass, int slot, int mods,
|
||
|
int typecode); /* JVM-core */
|
||
|
|
||
|
private static native int setInt0(Object objOrClass, int slot, int mods,
|
||
|
int typecode, int value); /* JVM-core */
|
||
|
|
||
|
private static native long getLong0(Object objOrClass,
|
||
|
int slot, int mods); /* JVM-core */
|
||
|
|
||
|
private static native int setLong0(Object objOrClass, long value,
|
||
|
int slot, int mods); /* JVM-core */
|
||
|
|
||
|
private static native float getFloat0(Object objOrClass,
|
||
|
int slot, int mods); /* JVM-core */
|
||
|
|
||
|
private static native int setFloat0(Object objOrClass, float value,
|
||
|
int slot, int mods); /* JVM-core */
|
||
|
|
||
|
private static native double getDouble0(Object objOrClass,
|
||
|
int slot, int mods); /* JVM-core */
|
||
|
|
||
|
private static native int setDouble0(Object objOrClass, double value,
|
||
|
int slot, int mods); /* JVM-core */
|
||
|
|
||
|
private static native Object get0(Object objOrClass,
|
||
|
int slot, int mods); /* JVM-core */
|
||
|
|
||
|
private static native int set0(Object objOrClass, Object value,
|
||
|
int slot, int mods); /* JVM-core */
|
||
|
|
||
|
private static native long objectFieldOffset0(Class aclass,
|
||
|
int slot); /* JVM-core */
|
||
|
}
|