/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.lang.reflect;
import java.lang.reflect.VMCommonLibrarySupport;
import org.jikesrvm.classloader.RVMClass;
import org.jikesrvm.classloader.RVMField;
import org.jikesrvm.classloader.RVMMember;
import org.jikesrvm.classloader.RVMType;
import org.jikesrvm.classloader.TypeReference;
import org.jikesrvm.objectmodel.ObjectModel;
import org.jikesrvm.runtime.RuntimeEntrypoints;
import org.jikesrvm.VM;
/**
* This class must be implemented by the VM vendor. This class models a field.
* Information about the field can be accessed, and the field's value can be
* accessed dynamically.
*
*/
public final class Field extends AccessibleObject implements Member {
private final RVMField vmField;
/**
* Constructor
*/
Field(RVMField vmField){
this.vmField = vmField;
}
/**
* Prevent this class from being instantiated
*/
private Field(){
vmField = null;
}
public boolean isSynthetic() {
return super.isSynthetic();
}
/**
* <p>
* Returns the String representation of the field's declaration, including
* the type parameters.
* </p>
*
* @return An instance of String.
* @since 1.5
*/
public String toGenericString() {
throw new Error("TODO");
}
/**
* <p>
* Indicates whether or not this field is an enumeration constant.
* </p>
*
* @return A value of <code>true</code> if this field is an enumeration
* constant, otherwise <code>false</code>.
* @since 1.5
*/
public boolean isEnumConstant() {
return (getModifiers() & Modifier.ENUM) != 0;
}
/**
* <p>
* Gets the declared type of this field.
* </p>
*
* @return An instance of {@link Type}.
* @throws GenericSignatureFormatError if the generic method signature is
* invalid.
* @throws TypeNotPresentException if the component type points to a missing
* type.
* @throws MalformedParameterizedTypeException if the component type points
* to a type that can't be instantiated for some reason.
* @since 1.5
*/
public Type getGenericType() {
throw new Error("TODO");
}
/**
* Compares the specified object to this Field and answer if they are equal.
* The object must be an instance of Field with the same defining class and
* name.
*
* @param object the object to compare
* @return true if the specified object is equal to this Field, false
* otherwise
* @see #hashCode
*/
@Override
public boolean equals(Object object) {
if (object instanceof Field) {
Field that = (Field)object;
return this.vmField == that.vmField;
} else {
return false;
}
}
/**
* Return the value of the field in the specified object. This reproduces
* the effect of <code>object.fieldName</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* The value of the field is returned. If the type of this field is a base
* type, the field value is automatically wrapped.
*
* @param object
* the object to access
* @return the field value, possibly wrapped
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public Object get(Object object) throws IllegalAccessException, IllegalArgumentException {
return VMCommonLibrarySupport.get(object, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Return the value of the field in the specified object as a boolean. This
* reproduces the effect of <code>object.fieldName</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
*
* @param object
* the object to access
* @return the field value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public boolean getBoolean(Object object)
throws IllegalAccessException, IllegalArgumentException{
return VMCommonLibrarySupport.getBoolean(object, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Return the value of the field in the specified object as a byte. This
* reproduces the effect of <code>object.fieldName</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
*
* @param object
* the object to access
* @return the field value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public byte getByte(Object object) throws IllegalAccessException,
IllegalArgumentException{
return VMCommonLibrarySupport.getByte(object, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Return the value of the field in the specified object as a char. This
* reproduces the effect of <code>object.fieldName</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
*
* @param object
* the object to access
* @return the field value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public char getChar(Object object) throws IllegalAccessException,
IllegalArgumentException {
return VMCommonLibrarySupport.getChar(object, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Return the {@link Class} associated with the class that defined this
* field.
*
* @return the declaring class
*/
public Class<?> getDeclaringClass() {
return (Class<?>)vmField.getDeclaringClass().getClassForType();
}
/**
* Return the value of the field in the specified object as a double. This
* reproduces the effect of <code>object.fieldName</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
*
* @param object
* the object to access
* @return the field value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public double getDouble(Object object)
throws IllegalAccessException, IllegalArgumentException {
return VMCommonLibrarySupport.getDouble(object, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Return the value of the field in the specified object as a float. This
* reproduces the effect of <code>object.fieldName</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
*
* @param object
* the object to access
* @return the field value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public float getFloat(Object object) throws IllegalAccessException,
IllegalArgumentException {
return VMCommonLibrarySupport.getFloat(object, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Return the value of the field in the specified object as an int. This
* reproduces the effect of <code>object.fieldName</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
*
* @param object
* the object to access
* @return the field value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public int getInt(Object object) throws IllegalAccessException, IllegalArgumentException {
return VMCommonLibrarySupport.getInt(object, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Return the value of the field in the specified object as a long. This
* reproduces the effect of <code>object.fieldName</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
*
* @param object
* the object to access
* @return the field value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public long getLong(Object object) throws IllegalAccessException,
IllegalArgumentException {
return VMCommonLibrarySupport.getLong(object, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Return the modifiers for the modeled field. The Modifier class should be
* used to decode the result.
*
* @return the modifiers
* @see java.lang.reflect.Modifier
*/
public int getModifiers() {
return super.getModifiers();
}
/**
* Return the name of the modeled field.
*
* @return the name
*/
public String getName() {
return vmField.getName().toString();
}
/**
* Return the value of the field in the specified object as a short. This
* reproduces the effect of <code>object.fieldName</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
*
* @param object
* the object to access
* @return the field value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public short getShort(Object object) throws IllegalAccessException,
IllegalArgumentException {
return VMCommonLibrarySupport.getShort(object, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Return the {@link Class} associated with the type of this field.
*
* @return the type
*/
public Class<?> getType() {
return vmField.getType().resolve().getClassForType();
}
/**
* Answers an integer hash code for the receiver. Objects which are equal
* answer the same value for this method.
* <p>
* The hash code for a Field is the hash code of the field's name.
*
* @return the receiver's hash
* @see #equals
*/
@Override
public int hashCode() {
return getName().hashCode();
}
/**
* Set the value of the field in the specified object to the boolean value.
* This reproduces the effect of <code>object.fieldName = value</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* If the field type is a base type, the value is automatically unwrapped.
* If the unwrap fails, an IllegalArgumentException is thrown. If the value
* cannot be converted to the field type via a widening conversion, an
* IllegalArgumentException is thrown.
*
* @param object
* the object to access
* @param value
* the new value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public void set(Object object, Object value)
throws IllegalAccessException, IllegalArgumentException {
VMCommonLibrarySupport.set(object, value, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Set the value of the field in the specified object to the boolean value.
* This reproduces the effect of <code>object.fieldName = value</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* If the value cannot be converted to the field type via a widening
* conversion, an IllegalArgumentException is thrown.
*
* @param object
* the object to access
* @param value
* the new value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public void setBoolean(Object object, boolean value)
throws IllegalAccessException, IllegalArgumentException {
VMCommonLibrarySupport.setBoolean(object, value, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Set the value of the field in the specified object to the byte value.
* This reproduces the effect of <code>object.fieldName = value</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* If the value cannot be converted to the field type via a widening
* conversion, an IllegalArgumentException is thrown.
*
* @param object
* the object to access
* @param value
* the new value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public void setByte(Object object, byte value)
throws IllegalAccessException, IllegalArgumentException {
VMCommonLibrarySupport.setByte(object, value, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Set the value of the field in the specified object to the char value.
* This reproduces the effect of <code>object.fieldName = value</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* If the value cannot be converted to the field type via a widening
* conversion, an IllegalArgumentException is thrown.
*
* @param object
* the object to access
* @param value
* the new value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public void setChar(Object object, char value)
throws IllegalAccessException, IllegalArgumentException {
VMCommonLibrarySupport.setChar(object, value, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Set the value of the field in the specified object to the double value.
* This reproduces the effect of <code>object.fieldName = value</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* If the value cannot be converted to the field type via a widening
* conversion, an IllegalArgumentException is thrown.
*
* @param object
* the object to access
* @param value
* the new value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public void setDouble(Object object, double value)
throws IllegalAccessException, IllegalArgumentException {
VMCommonLibrarySupport.setDouble(object, value, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Set the value of the field in the specified object to the float value.
* This reproduces the effect of <code>object.fieldName = value</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* If the value cannot be converted to the field type via a widening
* conversion, an IllegalArgumentException is thrown.
*
* @param object
* the object to access
* @param value
* the new value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public void setFloat(Object object, float value)
throws IllegalAccessException, IllegalArgumentException {
VMCommonLibrarySupport.setFloat(object, value, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Set the value of the field in the specified object to the int value. This
* reproduces the effect of <code>object.fieldName = value</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* If the value cannot be converted to the field type via a widening
* conversion, an IllegalArgumentException is thrown.
*
* @param object
* the object to access
* @param value
* the new value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public void setInt(Object object, int value)
throws IllegalAccessException, IllegalArgumentException {
VMCommonLibrarySupport.setInt(object, value, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Set the value of the field in the specified object to the long value.
* This reproduces the effect of <code>object.fieldName = value</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* If the value cannot be converted to the field type via a widening
* conversion, an IllegalArgumentException is thrown.
*
* @param object
* the object to access
* @param value
* the new value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public void setLong(Object object, long value)
throws IllegalAccessException, IllegalArgumentException {
VMCommonLibrarySupport.setLong(object, value, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Set the value of the field in the specified object to the short value.
* This reproduces the effect of <code>object.fieldName = value</code>
* <p>
* If the modeled field is static, the object argument is ignored.
* Otherwise, if the object is null, a NullPointerException is thrown. If
* the object is not an instance of the declaring class of the method, an
* IllegalArgumentException is thrown.
* <p>
* If this Field object is enforcing access control (see AccessibleObject)
* and the modeled field is not accessible from the current context, an
* IllegalAccessException is thrown.
* <p>
* If the value cannot be converted to the field type via a widening
* conversion, an IllegalArgumentException is thrown.
*
* @param object
* the object to access
* @param value
* the new value
* @throws NullPointerException
* if the object is null and the field is non-static
* @throws IllegalArgumentException
* if the object is not compatible with the declaring class
* @throws IllegalAccessException
* if modeled field is not accessible
*/
public void setShort(Object object, short value)
throws IllegalAccessException, IllegalArgumentException {
VMCommonLibrarySupport.setShort(object, value, vmField, this, RVMClass.getClassFromStackFrame(1));
}
/**
* Answers a string containing a concise, human-readable description of the
* receiver.
* <p>
* The format of the string is:
* <ul>
* <li>modifiers (if any)
* <li>return type
* <li>declaring class name
* <li>'.'
* <li>field name
* </ul>
* <p>
* For example:
* <code>public static java.io.InputStream java.lang.System.in</code>
*
* @return a printable representation for the receiver
*/
public String toString() {
StringBuilder sb = new StringBuilder(80);
// append modifiers if any
int modifier = getModifiers();
if (modifier != 0) {
sb.append(Modifier.toString(modifier)).append(' ');
}
// append return type
appendArrayType(sb, getType());
sb.append(' ');
// append full field name
sb.append(getDeclaringClass().getName()).append('.').append(getName());
return sb.toString();
}
/* ---- Non-API methods ---- */
/**
* Get the VM member implementation. Package protected to stop outside use.
*/
@Override
RVMMember getVMMember() {
return vmField;
}
}