Xposed reflected field parsed

In XposedBridge source ( https://github.com/rovo89/XposedBridge), the method of the reflected field `de.robv.android.xposed.XposedHelpers` encapsulated inside the class. Xposed below to see how to get and set fields are worth it

Gets the value of the field

Gets the field values ​​are many methods, there are ways to obtain basic type field value (getIntField, getLongField, getDoubleField ...), there are ways to get the value of the object type field. They achieve the same. We get the object type field value, for example, to analyze how the reflection values ​​acquired Xposed field objects. this feature of the class getObjectField method XposedHelpers

public static Object getObjectField(Object obj, String fieldName) {
    try {
        return findField(obj.getClass(), fieldName).get(obj);
    } catch (IllegalAccessException e) {
        // should not happen
        XposedBridge.log(e);
        throw new IllegalAccessError(e.getMessage());
    } catch (IllegalArgumentException e) {
        throw e;
    }
}

getObjectFieldThere are two parameters: the object belongs to a field is to be obtained, the other is the name of the field.
getObjectFieldThe main call findFieldmethod and call findFieldset methods return the object to see findField method:

public static Field findField(Class<?> clazz, String fieldName) {
    String fullFieldName = clazz.getName() + '#' + fieldName;

    if (fieldCache.containsKey(fullFieldName)) {
        Field field = fieldCache.get(fullFieldName);
        if (field == null)
            throw new NoSuchFieldError(fullFieldName);
        return field;
    }

    try {
        Field field = findFieldRecursiveImpl(clazz, fieldName);
        field.setAccessible(true);
        fieldCache.put(fullFieldName, field);
        return field;
    } catch (NoSuchFieldException e) {
        fieldCache.put(fullFieldName, null);
        throw new NoSuchFieldError(fullFieldName);
    }
}

findFieldStart method, first stitching a full field name. Then determine whether there is a cache in this field based on the full field names, if you remove the field from the cache, you do not look at, so the child can do to improve the reflection rate. If you find out from the cache before a null value, on behalf of this field too, I can not find, and throw an exception.

Cache name fieldCache, it is a HashMap.

private static final HashMap<String, Field> fieldCache = new HashMap<>();

If the cache does not have this field, call the findFieldRecursiveImplFind field:

private static Field findFieldRecursiveImpl(Class<?> clazz, String fieldName) throws NoSuchFieldException {
    try {
        return clazz.getDeclaredField(fieldName);
    } catch (NoSuchFieldException e) {
        while (true) {
            clazz = clazz.getSuperclass();
            if (clazz == null || clazz.equals(Object.class))
                break;

            try {
                return clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException ignored) {}
        }
        throw e;
    }
}

findFieldRecursiveImplFirstly, look at the Class class that comes through there is no such field, if returned Field object. If not, open a infinite loop looking for from its parent class, if the class has no parent or have been found Objectclass also can not be found to this method, the description field of this class is really not looking, throw an exception. If you find this field in its parent class, returns a field object.

findFieldRecursiveImpl end of the call, will be back after findField the second half:

public static Field findField(Class<?> clazz, String fieldName) {
    ......
    try {
        Field field = findFieldRecursiveImpl(clazz, fieldName);
        field.setAccessible(true);
        fieldCache.put(fullFieldName, field);
        return field;
    } catch (NoSuchFieldException e) {
        fieldCache.put(fullFieldName, null);
        throw new NoSuchFieldError(fullFieldName);
    }
}

If findFieldRecursiveImpl not throw an exception, then the field will be added to the cache, and returns this field. If you throw an exception if findFieldRecursiveImpl, also placed in the cache, but put a null value.

findFieldEnd of the process, back to the original getObjectFieldmethod, call the getmethod to return the field to store object values

Value of a field

And a method to get the value of the field, like setting method also has many fields, their implementation is also very much the same we take a look at `setObjectField`` of these methods:

public static void setObjectField(Object obj, String fieldName, Object value) {
    try {
        findField(obj.getClass(), fieldName).set(obj, value);
    } catch (IllegalAccessException e) {
        // should not happen
        XposedBridge.log(e);
        throw new IllegalAccessError(e.getMessage());
    } catch (IllegalArgumentException e) {
        throw e;
    }
}

setObjectFieldAnd explain the above method getObjectFieldis almost the same, but also by calling findFieldto give the Field class object method. The difference is that, setObjectFieldafter the call is its object to give Field set method to set the value of the field

Guess you like

Origin www.cnblogs.com/luoyesiqiu/p/11283687.html