To resolve an unresolved symbolic reference from D to a field in a class or interface C, the symbolic reference to C given by the field reference must first be resolved (§220.127.116.11). Therefore, any exception that can be thrown as a result of failure of resolution of a class or interface reference can be thrown as a result of failure of field resolution. If the reference to C can be successfully resolved, an exception relating to the failure of resolution of the field reference itself can be thrown. When resolving a field reference, field resolution first attempts to look up the referenced field in C and its superclasses: 1. If C declares a field with the name and descriptor specified by the field reference, field lookup succeeds. The declared field is the result of the field lookup. 2. Otherwise, field lookup is applied recursively to the direct superinterfaces of the specified class or interface C. 3. Otherwise, if C has a superclass S, field lookup is applied recursively to S. 4. Otherwise, field lookup fails. Then, the result of field resolution is determined:
If field lookup failed, field resolution throws a NoSuchFieldError.
Otherwise, field lookup succeeded. Access control is applied for the access from D to the field which is the result of field lookup (§5.4.4). Then:
If access control failed, field resolution fails for the same reason.
Otherwise, access control succeeded. Loading constraints are imposed, as follows.
Let <E, L1> be the class or interface in which the referenced field is actually declared. Let L2 be the defining loader of D. Given that the type of the referenced field is Tf: if Tf is not an array type, let T be Tf; otherwise, let T be the element type of Tf.
The Java Virtual Machine imposes the loading constraint that TL1 = TL2.
If imposing this constraint results in any loading constraints being violated (§5.3.4), then field resolution fails. Otherwise, field resolution succeeds.