code: private static Field asSetableField(Field field, Object target, Class<?> valueType, Object value,
  			boolean makeAccessibleCopy)
  			throws IllegalAccessException {
  		// Must do the checks exactly in the same order as JVM if we want identical error messages.
  
  		// JVM doesn't do this, since it cannot happen without reloading, we do it first of all.
  		if (isDeleted(field)) {
  			throw Exceptions.noSuchFieldError(field);
  		}
  
  		Class<?> clazz = field.getDeclaringClass();
  		int mods = field.getModifiers();
  		if (field.isAccessible() || Modifier.isPublic(mods & jlClassGetModifiers(clazz))) {
  			//More expensive check not required / copy not required
  		}
  		else {
  			//More expensive check required
  			Class<?> callerClass = getCallerClass();
  			JVM.ensureMemberAccess(callerClass, clazz, target, mods);
  			if (makeAccessibleCopy) {
  				//TODO: This code is not covered by a test. It needs a non-reloadable type with non-public
  				//  field, being accessed reflectively from a context that is "priviliged" to access it without setting the access flag.
  
  				field = JVM.copyField(field); // copy: we must not change accessible flag on original field!
  				field.setAccessible(true);
  			}
  		}
  		if (isPrimitive(valueType)) {
  			//It seems for primitive types, the order of the checks (in Sun JVM) is different!
  			typeCheckFieldSet(field, valueType, value);
  			if (!field.isAccessible() && Modifier.isFinal(mods)) {
  				throw Exceptions.illegalSetFinalFieldException(field, field.getType(), coerce(value, field.getType()));
  			}
  		}
  		else {
  			if (!field.isAccessible() && Modifier.isFinal(mods)) {
  				throw Exceptions.illegalSetFinalFieldException(field, valueType, value);
  			}
  			typeCheckFieldSet(field, valueType, value);
  		}
  		return makeAccessibleCopy ? field : null;
  	}
docs: Performs all necessary checks that need to be done before a field set should be allowed.
  
  @throws IllegalAccessException