1717
1818package org .dizitart .no2 .repository ;
1919
20+ import java .lang .invoke .MethodHandle ;
21+ import java .lang .invoke .MethodHandles ;
2022import java .lang .reflect .Field ;
2123import java .lang .reflect .Method ;
2224
2325/**
2426 * Helper class to access field values, handling both regular fields and interface properties.
2527 * For interface properties (synthetic fields from InterfacePropertyHolder), this class
2628 * finds and accesses the actual field on the concrete implementation object.
29+ *
30+ * Uses MethodHandles for improved security and performance (Android API 26+, available in API 30).
2731 *
2832 * @author Anindya Chatterjee
2933 * @since 4.3.2
@@ -32,7 +36,7 @@ class FieldAccessHelper {
3236
3337 /**
3438 * Gets the value of a field from an object, handling both regular and interface property fields.
35- * Uses reflection with appropriate access control .
39+ * Uses MethodHandles for improved security and performance (Android API 26+) .
3640 *
3741 * @param field the field to access
3842 * @param obj the object to get the value from
@@ -52,7 +56,7 @@ static Object get(Field field, Object obj) throws IllegalAccessException {
5256
5357 /**
5458 * Sets the value of a field on an object, handling both regular and interface property fields.
55- * Uses reflection with appropriate access control .
59+ * Uses MethodHandles for improved security and performance (Android API 26+) .
5660 *
5761 * @param field the field to set
5862 * @param obj the object to set the value on
@@ -71,23 +75,37 @@ static void set(Field field, Object obj, Object value) throws IllegalAccessExcep
7175 }
7276
7377 /**
74- * Gets the value of a field, handling access control appropriately.
78+ * Gets the value of a field using MethodHandles for secure access.
79+ * Uses unreflect approach compatible with Android API 26+.
7580 */
7681 private static Object getFieldValue (Field field , Object obj ) throws IllegalAccessException {
77- if (!field .isAccessible ()) {
82+ try {
83+ // Use MethodHandles.lookup().unreflect which is available since Android API 26
84+ // This is more secure than setAccessible but requires the field to be accessible
7885 field .setAccessible (true );
86+ MethodHandles .Lookup lookup = MethodHandles .lookup ();
87+ MethodHandle getter = lookup .unreflectGetter (field );
88+ return getter .invokeWithArguments (obj );
89+ } catch (Throwable e ) {
90+ throw new IllegalAccessException ("Cannot access field " + field .getName () + ": " + e .getMessage ());
7991 }
80- return field .get (obj );
8192 }
8293
8394 /**
84- * Sets the value of a field, handling access control appropriately.
95+ * Sets the value of a field using MethodHandles for secure access.
96+ * Uses unreflect approach compatible with Android API 26+.
8597 */
8698 private static void setFieldValue (Field field , Object obj , Object value ) throws IllegalAccessException {
87- if (!field .isAccessible ()) {
99+ try {
100+ // Use MethodHandles.lookup().unreflect which is available since Android API 26
101+ // This is more secure than direct setAccessible + set
88102 field .setAccessible (true );
103+ MethodHandles .Lookup lookup = MethodHandles .lookup ();
104+ MethodHandle setter = lookup .unreflectSetter (field );
105+ setter .invokeWithArguments (obj , value );
106+ } catch (Throwable e ) {
107+ throw new IllegalAccessException ("Cannot set field " + field .getName () + ": " + e .getMessage ());
89108 }
90- field .set (obj , value );
91109 }
92110
93111 /**
@@ -146,17 +164,23 @@ private static void setPropertyValue(Object obj, String propertyName, Object val
146164 }
147165
148166 /**
149- * Invokes a method, handling access control appropriately.
167+ * Invokes a method using MethodHandles for improved security.
168+ * Uses unreflect approach compatible with Android API 26+.
150169 */
151170 private static Object invokeMethod (Method method , Object obj , Object ... args ) throws IllegalAccessException {
152171 try {
153- if (!method .isAccessible ()) {
154- method .setAccessible (true );
172+ // Use MethodHandles.lookup().unreflect which is available since Android API 26
173+ method .setAccessible (true );
174+ MethodHandles .Lookup lookup = MethodHandles .lookup ();
175+ MethodHandle methodHandle = lookup .unreflect (method );
176+ if (args .length == 0 ) {
177+ return methodHandle .invokeWithArguments (obj );
178+ } else {
179+ return methodHandle .invokeWithArguments (obj , args [0 ]);
155180 }
156- return method .invoke (obj , args );
157181 } catch (IllegalAccessException e ) {
158182 throw e ;
159- } catch (Exception e ) {
183+ } catch (Throwable e ) {
160184 throw new IllegalAccessException ("Cannot invoke method " + method .getName () + ": " + e .getMessage ());
161185 }
162186 }
0 commit comments