1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.  Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 */
26
27package java.lang.reflect;
28
29import sun.reflect.CallerSensitive;
30import sun.reflect.Reflection;
31import java.lang.annotation.Annotation;
32import java.util.Map;
33import com.android.dex.Dex;
34import libcore.reflect.GenericSignatureParser;
35import java.util.List;
36
37
38/**
39 * A {@code Field} provides information about, and dynamic access to, a
40 * single field of a class or an interface.  The reflected field may
41 * be a class (static) field or an instance field.
42 *
43 * <p>A {@code Field} permits widening conversions to occur during a get or
44 * set access operation, but throws an {@code IllegalArgumentException} if a
45 * narrowing conversion would occur.
46 *
47 * @see Member
48 * @see java.lang.Class
49 * @see java.lang.Class#getFields()
50 * @see java.lang.Class#getField(String)
51 * @see java.lang.Class#getDeclaredFields()
52 * @see java.lang.Class#getDeclaredField(String)
53 *
54 * @author Kenneth Russell
55 * @author Nakul Saraiya
56 */
57public final
58class Field extends AccessibleObject implements Member {
59
60    private int accessFlags;
61    private Class<?> declaringClass;
62    private int dexFieldIndex;
63    private int offset;
64    private Class<?> type;
65
66    private Field() {
67    }
68
69    /**
70     * Returns the {@code Class} object representing the class or interface
71     * that declares the field represented by this {@code Field} object.
72     */
73    public Class<?> getDeclaringClass() {
74        return declaringClass;
75    }
76
77    /**
78     * Returns the name of the field represented by this {@code Field} object.
79     */
80    public String getName() {
81        if (dexFieldIndex == -1) {
82            // Proxy classes have 1 synthesized static field with no valid dex index.
83            if (!declaringClass.isProxy()) {
84                throw new AssertionError();
85            }
86            return "throws";
87        }
88        Dex dex = declaringClass.getDex();
89        int nameIndex = dex.nameIndexFromFieldIndex(dexFieldIndex);
90        return declaringClass.getDexCacheString(dex, nameIndex);
91    }
92
93    /**
94     * Returns the Java language modifiers for the field represented
95     * by this {@code Field} object, as an integer. The {@code Modifier} class should
96     * be used to decode the modifiers.
97     *
98     * @see Modifier
99     */
100    public int getModifiers() {
101        return accessFlags & 0xffff;  // mask out bits not used by Java
102    }
103
104    /**
105     * Returns {@code true} if this field represents an element of
106     * an enumerated type; returns {@code false} otherwise.
107     *
108     * @return {@code true} if and only if this field represents an element of
109     * an enumerated type.
110     * @since 1.5
111     */
112    public boolean isEnumConstant() {
113        return (getModifiers() & Modifier.ENUM) != 0;
114    }
115
116    /**
117     * Returns {@code true} if this field is a synthetic
118     * field; returns {@code false} otherwise.
119     *
120     * @return true if and only if this field is a synthetic
121     * field as defined by the Java Language Specification.
122     * @since 1.5
123     */
124    public boolean isSynthetic() {
125        return Modifier.isSynthetic(getModifiers());
126    }
127
128    /**
129     * Returns a {@code Class} object that identifies the
130     * declared type for the field represented by this
131     * {@code Field} object.
132     *
133     * @return a {@code Class} object identifying the declared
134     * type of the field represented by this object
135     */
136    public Class<?> getType() {
137        return type;
138    }
139
140    /**
141     * Returns a {@code Type} object that represents the declared type for
142     * the field represented by this {@code Field} object.
143     *
144     * <p>If the {@code Type} is a parameterized type, the
145     * {@code Type} object returned must accurately reflect the
146     * actual type parameters used in the source code.
147     *
148     * <p>If the type of the underlying field is a type variable or a
149     * parameterized type, it is created. Otherwise, it is resolved.
150     *
151     * @return a {@code Type} object that represents the declared type for
152     *     the field represented by this {@code Field} object
153     * @throws GenericSignatureFormatError if the generic field
154     *     signature does not conform to the format specified in
155     *     <cite>The Java&trade; Virtual Machine Specification</cite>
156     * @throws TypeNotPresentException if the generic type
157     *     signature of the underlying field refers to a non-existent
158     *     type declaration
159     * @throws MalformedParameterizedTypeException if the generic
160     *     signature of the underlying field refers to a parameterized type
161     *     that cannot be instantiated for any reason
162     * @since 1.5
163     */
164    public Type getGenericType() {
165        String signatureAttribute = getSignatureAttribute();
166        ClassLoader cl = declaringClass.getClassLoader();
167        GenericSignatureParser parser = new GenericSignatureParser(cl);
168        parser.parseForField(declaringClass, signatureAttribute);
169        Type genericType = parser.fieldType;
170        if (genericType == null) {
171            genericType = getType();
172        }
173        return genericType;
174    }
175
176    private String getSignatureAttribute() {
177        String[] annotation = getSignatureAnnotation();
178        if (annotation == null) {
179            return null;
180        }
181        StringBuilder result = new StringBuilder();
182        for (String s : annotation) {
183            result.append(s);
184        }
185        return result.toString();
186    }
187    private native String[] getSignatureAnnotation();
188
189
190    /**
191     * Compares this {@code Field} against the specified object.  Returns
192     * true if the objects are the same.  Two {@code Field} objects are the same if
193     * they were declared by the same class and have the same name
194     * and type.
195     */
196    public boolean equals(Object obj) {
197        if (obj != null && obj instanceof Field) {
198            Field other = (Field)obj;
199            return (getDeclaringClass() == other.getDeclaringClass())
200                && (getName() == other.getName())
201                && (getType() == other.getType());
202        }
203        return false;
204    }
205
206    /**
207     * Returns a hashcode for this {@code Field}.  This is computed as the
208     * exclusive-or of the hashcodes for the underlying field's
209     * declaring class name and its name.
210     */
211    public int hashCode() {
212        return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
213    }
214
215    /**
216     * Returns a string describing this {@code Field}.  The format is
217     * the access modifiers for the field, if any, followed
218     * by the field type, followed by a space, followed by
219     * the fully-qualified name of the class declaring the field,
220     * followed by a period, followed by the name of the field.
221     * For example:
222     * <pre>
223     *    public static final int java.lang.Thread.MIN_PRIORITY
224     *    private int java.io.FileDescriptor.fd
225     * </pre>
226     *
227     * <p>The modifiers are placed in canonical order as specified by
228     * "The Java Language Specification".  This is {@code public},
229     * {@code protected} or {@code private} first, and then other
230     * modifiers in the following order: {@code static}, {@code final},
231     * {@code transient}, {@code volatile}.
232     */
233    public String toString() {
234        int mod = getModifiers();
235        return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
236            + getTypeName(getType()) + " "
237            + getTypeName(getDeclaringClass()) + "."
238            + getName());
239    }
240
241    /**
242     * Returns a string describing this {@code Field}, including
243     * its generic type.  The format is the access modifiers for the
244     * field, if any, followed by the generic field type, followed by
245     * a space, followed by the fully-qualified name of the class
246     * declaring the field, followed by a period, followed by the name
247     * of the field.
248     *
249     * <p>The modifiers are placed in canonical order as specified by
250     * "The Java Language Specification".  This is {@code public},
251     * {@code protected} or {@code private} first, and then other
252     * modifiers in the following order: {@code static}, {@code final},
253     * {@code transient}, {@code volatile}.
254     *
255     * @return a string describing this {@code Field}, including
256     * its generic type
257     *
258     * @since 1.5
259     */
260    public String toGenericString() {
261        int mod = getModifiers();
262        Type fieldType = getGenericType();
263        return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
264            +  ((fieldType instanceof Class) ?
265                getTypeName((Class)fieldType): fieldType.toString())+ " "
266            + getTypeName(getDeclaringClass()) + "."
267            + getName());
268    }
269
270    /**
271     * Returns the value of the field represented by this {@code Field}, on
272     * the specified object. The value is automatically wrapped in an
273     * object if it has a primitive type.
274     *
275     * <p>The underlying field's value is obtained as follows:
276     *
277     * <p>If the underlying field is a static field, the {@code obj} argument
278     * is ignored; it may be null.
279     *
280     * <p>Otherwise, the underlying field is an instance field.  If the
281     * specified {@code obj} argument is null, the method throws a
282     * {@code NullPointerException}. If the specified object is not an
283     * instance of the class or interface declaring the underlying
284     * field, the method throws an {@code IllegalArgumentException}.
285     *
286     * <p>If this {@code Field} object is enforcing Java language access control, and
287     * the underlying field is inaccessible, the method throws an
288     * {@code IllegalAccessException}.
289     * If the underlying field is static, the class that declared the
290     * field is initialized if it has not already been initialized.
291     *
292     * <p>Otherwise, the value is retrieved from the underlying instance
293     * or static field.  If the field has a primitive type, the value
294     * is wrapped in an object before being returned, otherwise it is
295     * returned as is.
296     *
297     * <p>If the field is hidden in the type of {@code obj},
298     * the field's value is obtained according to the preceding rules.
299     *
300     * @param object object from which the represented field's value is
301     * to be extracted
302     * @return the value of the represented field in object
303     * {@code obj}; primitive values are wrapped in an appropriate
304     * object before being returned
305     *
306     * @exception IllegalAccessException    if this {@code Field} object
307     *              is enforcing Java language access control and the underlying
308     *              field is inaccessible.
309     * @exception IllegalArgumentException  if the specified object is not an
310     *              instance of the class or interface declaring the underlying
311     *              field (or a subclass or implementor thereof).
312     * @exception NullPointerException      if the specified object is null
313     *              and the field is an instance field.
314     * @exception ExceptionInInitializerError if the initialization provoked
315     *              by this method fails.
316     */
317    public native Object get(Object object)
318            throws IllegalAccessException, IllegalArgumentException;
319
320    /**
321     * Gets the value of a static or instance {@code boolean} field.
322     *
323     * @param object the object to extract the {@code boolean} value
324     * from
325     * @return the value of the {@code boolean} field
326     *
327     * @exception IllegalAccessException    if this {@code Field} object
328     *              is enforcing Java language access control and the underlying
329     *              field is inaccessible.
330     * @exception IllegalArgumentException  if the specified object is not
331     *              an instance of the class or interface declaring the
332     *              underlying field (or a subclass or implementor
333     *              thereof), or if the field value cannot be
334     *              converted to the type {@code boolean} by a
335     *              widening conversion.
336     * @exception NullPointerException      if the specified object is null
337     *              and the field is an instance field.
338     * @exception ExceptionInInitializerError if the initialization provoked
339     *              by this method fails.
340     * @see       Field#get
341     */
342    public native boolean getBoolean(Object object)
343            throws IllegalAccessException, IllegalArgumentException;
344
345    /**
346     * Gets the value of a static or instance {@code byte} field.
347     *
348     * @param object the object to extract the {@code byte} value
349     * from
350     * @return the value of the {@code byte} field
351     *
352     * @exception IllegalAccessException    if this {@code Field} object
353     *              is enforcing Java language access control and the underlying
354     *              field is inaccessible.
355     * @exception IllegalArgumentException  if the specified object is not
356     *              an instance of the class or interface declaring the
357     *              underlying field (or a subclass or implementor
358     *              thereof), or if the field value cannot be
359     *              converted to the type {@code byte} by a
360     *              widening conversion.
361     * @exception NullPointerException      if the specified object is null
362     *              and the field is an instance field.
363     * @exception ExceptionInInitializerError if the initialization provoked
364     *              by this method fails.
365     * @see       Field#get
366     */
367    public native byte getByte(Object object)
368            throws IllegalAccessException, IllegalArgumentException;
369
370    /**
371     * Gets the value of a static or instance field of type
372     * {@code char} or of another primitive type convertible to
373     * type {@code char} via a widening conversion.
374     *
375     * @param object the object to extract the {@code char} value
376     * from
377     * @return the value of the field converted to type {@code char}
378     *
379     * @exception IllegalAccessException    if this {@code Field} object
380     *              is enforcing Java language access control and the underlying
381     *              field is inaccessible.
382     * @exception IllegalArgumentException  if the specified object is not
383     *              an instance of the class or interface declaring the
384     *              underlying field (or a subclass or implementor
385     *              thereof), or if the field value cannot be
386     *              converted to the type {@code char} by a
387     *              widening conversion.
388     * @exception NullPointerException      if the specified object is null
389     *              and the field is an instance field.
390     * @exception ExceptionInInitializerError if the initialization provoked
391     *              by this method fails.
392     * @see Field#get
393     */
394    public native char getChar(Object object)
395            throws IllegalAccessException, IllegalArgumentException;
396
397    /**
398     * Gets the value of a static or instance field of type
399     * {@code short} or of another primitive type convertible to
400     * type {@code short} via a widening conversion.
401     *
402     * @param object the object to extract the {@code short} value
403     * from
404     * @return the value of the field converted to type {@code short}
405     *
406     * @exception IllegalAccessException    if this {@code Field} object
407     *              is enforcing Java language access control and the underlying
408     *              field is inaccessible.
409     * @exception IllegalArgumentException  if the specified object is not
410     *              an instance of the class or interface declaring the
411     *              underlying field (or a subclass or implementor
412     *              thereof), or if the field value cannot be
413     *              converted to the type {@code short} by a
414     *              widening conversion.
415     * @exception NullPointerException      if the specified object is null
416     *              and the field is an instance field.
417     * @exception ExceptionInInitializerError if the initialization provoked
418     *              by this method fails.
419     * @see       Field#get
420     */
421    public native short getShort(Object object)
422            throws IllegalAccessException, IllegalArgumentException;
423
424    /**
425     * Gets the value of a static or instance field of type
426     * {@code int} or of another primitive type convertible to
427     * type {@code int} via a widening conversion.
428     *
429     * @param object the object to extract the {@code int} value
430     * from
431     * @return the value of the field converted to type {@code int}
432     *
433     * @exception IllegalAccessException    if this {@code Field} object
434     *              is enforcing Java language access control and the underlying
435     *              field is inaccessible.
436     * @exception IllegalArgumentException  if the specified object is not
437     *              an instance of the class or interface declaring the
438     *              underlying field (or a subclass or implementor
439     *              thereof), or if the field value cannot be
440     *              converted to the type {@code int} by a
441     *              widening conversion.
442     * @exception NullPointerException      if the specified object is null
443     *              and the field is an instance field.
444     * @exception ExceptionInInitializerError if the initialization provoked
445     *              by this method fails.
446     * @see       Field#get
447     */
448    public native int getInt(Object object)
449            throws IllegalAccessException, IllegalArgumentException;
450
451    /**
452     * Gets the value of a static or instance field of type
453     * {@code long} or of another primitive type convertible to
454     * type {@code long} via a widening conversion.
455     *
456     * @param object the object to extract the {@code long} value
457     * from
458     * @return the value of the field converted to type {@code long}
459     *
460     * @exception IllegalAccessException    if this {@code Field} object
461     *              is enforcing Java language access control and the underlying
462     *              field is inaccessible.
463     * @exception IllegalArgumentException  if the specified object is not
464     *              an instance of the class or interface declaring the
465     *              underlying field (or a subclass or implementor
466     *              thereof), or if the field value cannot be
467     *              converted to the type {@code long} by a
468     *              widening conversion.
469     * @exception NullPointerException      if the specified object is null
470     *              and the field is an instance field.
471     * @exception ExceptionInInitializerError if the initialization provoked
472     *              by this method fails.
473     * @see       Field#get
474     */
475    public native long getLong(Object object)
476            throws IllegalAccessException, IllegalArgumentException;
477
478    /**
479     * Gets the value of a static or instance field of type
480     * {@code float} or of another primitive type convertible to
481     * type {@code float} via a widening conversion.
482     *
483     * @param object the object to extract the {@code float} value
484     * from
485     * @return the value of the field converted to type {@code float}
486     *
487     * @exception IllegalAccessException    if this {@code Field} object
488     *              is enforcing Java language access control and the underlying
489     *              field is inaccessible.
490     * @exception IllegalArgumentException  if the specified object is not
491     *              an instance of the class or interface declaring the
492     *              underlying field (or a subclass or implementor
493     *              thereof), or if the field value cannot be
494     *              converted to the type {@code float} by a
495     *              widening conversion.
496     * @exception NullPointerException      if the specified object is null
497     *              and the field is an instance field.
498     * @exception ExceptionInInitializerError if the initialization provoked
499     *              by this method fails.
500     * @see Field#get
501     */
502    public native float getFloat(Object object)
503            throws IllegalAccessException, IllegalArgumentException;
504
505    /**
506     * Gets the value of a static or instance field of type
507     * {@code double} or of another primitive type convertible to
508     * type {@code double} via a widening conversion.
509     *
510     * @param object the object to extract the {@code double} value
511     * from
512     * @return the value of the field converted to type {@code double}
513     *
514     * @exception IllegalAccessException    if this {@code Field} object
515     *              is enforcing Java language access control and the underlying
516     *              field is inaccessible.
517     * @exception IllegalArgumentException  if the specified object is not
518     *              an instance of the class or interface declaring the
519     *              underlying field (or a subclass or implementor
520     *              thereof), or if the field value cannot be
521     *              converted to the type {@code double} by a
522     *              widening conversion.
523     * @exception NullPointerException      if the specified object is null
524     *              and the field is an instance field.
525     * @exception ExceptionInInitializerError if the initialization provoked
526     *              by this method fails.
527     * @see       Field#get
528     */
529    public native double getDouble(Object object)
530            throws IllegalAccessException, IllegalArgumentException;
531
532    /**
533     * Sets the field represented by this {@code Field} object on the
534     * specified object argument to the specified new value. The new
535     * value is automatically unwrapped if the underlying field has a
536     * primitive type.
537     *
538     * <p>The operation proceeds as follows:
539     *
540     * <p>If the underlying field is static, the {@code obj} argument is
541     * ignored; it may be null.
542     *
543     * <p>Otherwise the underlying field is an instance field.  If the
544     * specified object argument is null, the method throws a
545     * {@code NullPointerException}.  If the specified object argument is not
546     * an instance of the class or interface declaring the underlying
547     * field, the method throws an {@code IllegalArgumentException}.
548     *
549     * <p>If this {@code Field} object is enforcing Java language access control, and
550     * the underlying field is inaccessible, the method throws an
551     * {@code IllegalAccessException}.
552     *
553     * <p>If the underlying field is final, the method throws an
554     * {@code IllegalAccessException} unless {@code setAccessible(true)}
555     * has succeeded for this {@code Field} object
556     * and the field is non-static. Setting a final field in this way
557     * is meaningful only during deserialization or reconstruction of
558     * instances of classes with blank final fields, before they are
559     * made available for access by other parts of a program. Use in
560     * any other context may have unpredictable effects, including cases
561     * in which other parts of a program continue to use the original
562     * value of this field.
563     *
564     * <p>If the underlying field is of a primitive type, an unwrapping
565     * conversion is attempted to convert the new value to a value of
566     * a primitive type.  If this attempt fails, the method throws an
567     * {@code IllegalArgumentException}.
568     *
569     * <p>If, after possible unwrapping, the new value cannot be
570     * converted to the type of the underlying field by an identity or
571     * widening conversion, the method throws an
572     * {@code IllegalArgumentException}.
573     *
574     * <p>If the underlying field is static, the class that declared the
575     * field is initialized if it has not already been initialized.
576     *
577     * <p>The field is set to the possibly unwrapped and widened new value.
578     *
579     * <p>If the field is hidden in the type of {@code obj},
580     * the field's value is set according to the preceding rules.
581     *
582     * @param object the object whose field should be modified
583     * @param value the new value for the field of {@code obj}
584     * being modified
585     *
586     * @exception IllegalAccessException    if this {@code Field} object
587     *              is enforcing Java language access control and the underlying
588     *              field is either inaccessible or final.
589     * @exception IllegalArgumentException  if the specified object is not an
590     *              instance of the class or interface declaring the underlying
591     *              field (or a subclass or implementor thereof),
592     *              or if an unwrapping conversion fails.
593     * @exception NullPointerException      if the specified object is null
594     *              and the field is an instance field.
595     * @exception ExceptionInInitializerError if the initialization provoked
596     *              by this method fails.
597     */
598    public native void set(Object object, Object value)
599            throws IllegalAccessException, IllegalArgumentException;
600
601    /**
602     * Sets the value of a field as a {@code boolean} on the specified object.
603     * This method is equivalent to
604     * {@code set(obj, zObj)},
605     * where {@code zObj} is a {@code Boolean} object and
606     * {@code zObj.booleanValue() == z}.
607     *
608     * @param object the object whose field should be modified
609     * @param value   the new value for the field of {@code obj}
610     * being modified
611     *
612     * @exception IllegalAccessException    if this {@code Field} object
613     *              is enforcing Java language access control and the underlying
614     *              field is either inaccessible or final.
615     * @exception IllegalArgumentException  if the specified object is not an
616     *              instance of the class or interface declaring the underlying
617     *              field (or a subclass or implementor thereof),
618     *              or if an unwrapping conversion fails.
619     * @exception NullPointerException      if the specified object is null
620     *              and the field is an instance field.
621     * @exception ExceptionInInitializerError if the initialization provoked
622     *              by this method fails.
623     * @see       Field#set
624     */
625    public native void setBoolean(Object object, boolean value)
626            throws IllegalAccessException, IllegalArgumentException;
627
628    /**
629     * Sets the value of a field as a {@code byte} on the specified object.
630     * This method is equivalent to
631     * {@code set(obj, bObj)},
632     * where {@code bObj} is a {@code Byte} object and
633     * {@code bObj.byteValue() == b}.
634     *
635     * @param object the object whose field should be modified
636     * @param value   the new value for the field of {@code obj}
637     * being modified
638     *
639     * @exception IllegalAccessException    if this {@code Field} object
640     *              is enforcing Java language access control and the underlying
641     *              field is either inaccessible or final.
642     * @exception IllegalArgumentException  if the specified object is not an
643     *              instance of the class or interface declaring the underlying
644     *              field (or a subclass or implementor thereof),
645     *              or if an unwrapping conversion fails.
646     * @exception NullPointerException      if the specified object is null
647     *              and the field is an instance field.
648     * @exception ExceptionInInitializerError if the initialization provoked
649     *              by this method fails.
650     * @see       Field#set
651     */
652    public native void setByte(Object object, byte value)
653            throws IllegalAccessException, IllegalArgumentException;
654
655    /**
656     * Sets the value of a field as a {@code char} on the specified object.
657     * This method is equivalent to
658     * {@code set(obj, cObj)},
659     * where {@code cObj} is a {@code Character} object and
660     * {@code cObj.charValue() == c}.
661     *
662     * @param object the object whose field should be modified
663     * @param value   the new value for the field of {@code obj}
664     * being modified
665     *
666     * @exception IllegalAccessException    if this {@code Field} object
667     *              is enforcing Java language access control and the underlying
668     *              field is either inaccessible or final.
669     * @exception IllegalArgumentException  if the specified object is not an
670     *              instance of the class or interface declaring the underlying
671     *              field (or a subclass or implementor thereof),
672     *              or if an unwrapping conversion fails.
673     * @exception NullPointerException      if the specified object is null
674     *              and the field is an instance field.
675     * @exception ExceptionInInitializerError if the initialization provoked
676     *              by this method fails.
677     * @see       Field#set
678     */
679    public native void setChar(Object object, char value)
680            throws IllegalAccessException, IllegalArgumentException;
681
682    /**
683     * Sets the value of a field as a {@code short} on the specified object.
684     * This method is equivalent to
685     * {@code set(obj, sObj)},
686     * where {@code sObj} is a {@code Short} object and
687     * {@code sObj.shortValue() == s}.
688     *
689     * @param object the object whose field should be modified
690     * @param value   the new value for the field of {@code obj}
691     * being modified
692     *
693     * @exception IllegalAccessException    if this {@code Field} object
694     *              is enforcing Java language access control and the underlying
695     *              field is either inaccessible or final.
696     * @exception IllegalArgumentException  if the specified object is not an
697     *              instance of the class or interface declaring the underlying
698     *              field (or a subclass or implementor thereof),
699     *              or if an unwrapping conversion fails.
700     * @exception NullPointerException      if the specified object is null
701     *              and the field is an instance field.
702     * @exception ExceptionInInitializerError if the initialization provoked
703     *              by this method fails.
704     * @see       Field#set
705     */
706    public native void setShort(Object object, short value)
707            throws IllegalAccessException, IllegalArgumentException;
708
709    /**
710     * Sets the value of a field as an {@code int} on the specified object.
711     * This method is equivalent to
712     * {@code set(obj, iObj)},
713     * where {@code iObj} is a {@code Integer} object and
714     * {@code iObj.intValue() == i}.
715     *
716     * @param object the object whose field should be modified
717     * @param value   the new value for the field of {@code obj}
718     * being modified
719     *
720     * @exception IllegalAccessException    if this {@code Field} object
721     *              is enforcing Java language access control and the underlying
722     *              field is either inaccessible or final.
723     * @exception IllegalArgumentException  if the specified object is not an
724     *              instance of the class or interface declaring the underlying
725     *              field (or a subclass or implementor thereof),
726     *              or if an unwrapping conversion fails.
727     * @exception NullPointerException      if the specified object is null
728     *              and the field is an instance field.
729     * @exception ExceptionInInitializerError if the initialization provoked
730     *              by this method fails.
731     * @see       Field#set
732     */
733    public native void setInt(Object object, int value)
734            throws IllegalAccessException, IllegalArgumentException;
735
736    /**
737     * Sets the value of a field as a {@code long} on the specified object.
738     * This method is equivalent to
739     * {@code set(obj, lObj)},
740     * where {@code lObj} is a {@code Long} object and
741     * {@code lObj.longValue() == l}.
742     *
743     * @param object the object whose field should be modified
744     * @param value   the new value for the field of {@code obj}
745     * being modified
746     *
747     * @exception IllegalAccessException    if this {@code Field} object
748     *              is enforcing Java language access control and the underlying
749     *              field is either inaccessible or final.
750     * @exception IllegalArgumentException  if the specified object is not an
751     *              instance of the class or interface declaring the underlying
752     *              field (or a subclass or implementor thereof),
753     *              or if an unwrapping conversion fails.
754     * @exception NullPointerException      if the specified object is null
755     *              and the field is an instance field.
756     * @exception ExceptionInInitializerError if the initialization provoked
757     *              by this method fails.
758     * @see       Field#set
759     */
760    public native void setLong(Object object, long value)
761            throws IllegalAccessException, IllegalArgumentException;
762
763    /**
764     * Sets the value of a field as a {@code float} on the specified object.
765     * This method is equivalent to
766     * {@code set(obj, fObj)},
767     * where {@code fObj} is a {@code Float} object and
768     * {@code fObj.floatValue() == f}.
769     *
770     * @param object the object whose field should be modified
771     * @param value   the new value for the field of {@code obj}
772     * being modified
773     *
774     * @exception IllegalAccessException    if this {@code Field} object
775     *              is enforcing Java language access control and the underlying
776     *              field is either inaccessible or final.
777     * @exception IllegalArgumentException  if the specified object is not an
778     *              instance of the class or interface declaring the underlying
779     *              field (or a subclass or implementor thereof),
780     *              or if an unwrapping conversion fails.
781     * @exception NullPointerException      if the specified object is null
782     *              and the field is an instance field.
783     * @exception ExceptionInInitializerError if the initialization provoked
784     *              by this method fails.
785     * @see       Field#set
786     */
787    public native void setFloat(Object object, float value)
788            throws IllegalAccessException, IllegalArgumentException;
789
790    /**
791     * Sets the value of a field as a {@code double} on the specified object.
792     * This method is equivalent to
793     * {@code set(obj, dObj)},
794     * where {@code dObj} is a {@code Double} object and
795     * {@code dObj.doubleValue() == d}.
796     *
797     * @param object the object whose field should be modified
798     * @param value   the new value for the field of {@code obj}
799     * being modified
800     *
801     * @exception IllegalAccessException    if this {@code Field} object
802     *              is enforcing Java language access control and the underlying
803     *              field is either inaccessible or final.
804     * @exception IllegalArgumentException  if the specified object is not an
805     *              instance of the class or interface declaring the underlying
806     *              field (or a subclass or implementor thereof),
807     *              or if an unwrapping conversion fails.
808     * @exception NullPointerException      if the specified object is null
809     *              and the field is an instance field.
810     * @exception ExceptionInInitializerError if the initialization provoked
811     *              by this method fails.
812     * @see       Field#set
813     */
814    public native void setDouble(Object object, double value)
815            throws IllegalAccessException, IllegalArgumentException;
816
817    /*
818     * Utility routine to paper over array type names
819     */
820    static String getTypeName(Class<?> type) {
821        if (type.isArray()) {
822            try {
823                Class<?> cl = type;
824                int dimensions = 0;
825                while (cl.isArray()) {
826                    dimensions++;
827                    cl = cl.getComponentType();
828                }
829                StringBuffer sb = new StringBuffer();
830                sb.append(cl.getName());
831                for (int i = 0; i < dimensions; i++) {
832                    sb.append("[]");
833                }
834                return sb.toString();
835            } catch (Throwable e) { /*FALLTHRU*/ }
836        }
837        return type.getName();
838    }
839
840    /**
841     * @throws NullPointerException {@inheritDoc}
842     * @since 1.5
843     */
844    @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
845        if (annotationType == null) {
846            throw new NullPointerException("annotationType == null");
847        }
848        return getAnnotationNative(annotationType);
849    }
850    private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
851
852    @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
853        if (annotationType == null) {
854            throw new NullPointerException("annotationType == null");
855        }
856        return isAnnotationPresentNative(annotationType);
857    }
858    private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
859
860    /**
861     * @since 1.5
862     */
863    @Override public native Annotation[] getDeclaredAnnotations();
864
865    /**
866     * Returns the index of this field's ID in its dex file.
867     *
868     * @hide
869     */
870    public int getDexFieldIndex() {
871        return dexFieldIndex;
872    }
873
874    /**
875     * Returns the offset of the field within an instance, or for static fields, the class.
876     *
877     * @hide
878     */
879    public int getOffset() {
880        return offset;
881    }
882}
883