Understanding and Analyzing Java Reflection 7:17 Application:Eclipse (v4.2.2) Class:org.eclipse.osgi.util.NLS 300 static void load(final String bundleName,Class<?>clazz){ 302 final Field[]fieldArray clazz.getDeclaredFields(); 336 computeMissingMessages(.·,fieldArray,·..);·. 339} 267 static void computeMissingMessages(...,Field[]fieldArray,...){ 272 for (int i=0;i numFields;i++){ 273 Field field fieldArray[i]; 284 String value "NLS missing message:"+... 290 field.set(null,value);}... 2951 Fig.12.Self-inferencing property for a reflective field modification,deduced from the null argument and the dynamic type of the value argument at a set()call site. that the target field (to be modified in line 290)is static(from null)and its declared type must be java.lang.String or one of its supertypes(from the type of value). Definition 2.4(Self-Inferencing Property).For each reflective-action call site,its self-inferencing property comprises the information that can be used to infer its reflective targets,which consists of (1)all the information of its arguments(including receiver object),namely the number of arguments, their types,and(2)the possible downcasts on its returned values,and(3)the possible string values statically resolved at its corresponding class-retrieving and member-retrieving call sites. We argue that the self-inferencing property is inherent in most Java reflection code due to the characteristics of object-oriented programming and the Java reflection API.For example,the de- clared type of the object reflectively returned by get()and invoke()or created by newInstance() is always java.lang.Object.Therefore,the returned object must be first cast to a specific type before it is used as a regular object,except when its dynamic type is java.lang.Object or it will be used only as an receiver for the methods inherited from java.lang.Object;otherwise,the compilation would fail.As another example,the descriptor of a target method reflectively called at invoke()must be consistent with what is specified by its second argument (e.g.,parameters in line 175 of Figure 10);otherwise,exceptions would be thrown at runtime.These constraints should be exploited to enable resolving reflection in a disciplined way. The self-inferencing property not only helps resolve reflective calls more effectively when the values of string arguments are partially known(e.g.,when either a class name or a member name is known),but also provides an opportunity to resolve some reflective calls even if the string values are fully unknown.For example,in some Android apps,class and method names for reflective calls are encrypted for benign or malicious obfuscation,which "makes it impossible for any static analysis to recover the reflective call[48].However,this appears to be too pessimistic in our setting, because,in addition to the string values,some other self-inferencing hints are possibly available to facilitate reflection resolution.For example,given (A)invoke(o,{..))the class type of the target method can be inferred from the dynamic type of o(by pointer analysis),and the declared return type and descriptor of the target method can also be deduced from A and {..)respectively, as discussed above. ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019.Understanding and Analyzing Java Reflection 7:17 Application: Eclipse (v4.2.2) Class:org.eclipse.osgi.util.NLS 300 static void load(final String bundleName, Class<?> clazz) { 302 final Field[] fieldArray = clazz.getDeclaredFields(); 336 computeMissingMessages(..., fieldArray, ...); ... 339 } 267 static void computeMissingMessages(..., Field[] fieldArray,...) { 272 for (int i = 0; i < numFields; i++) { 273 Field field = fieldArray[i]; 284 String value = "NLS missing message: " + ...; 290 field.set(null, value); } ... 295 } Fig. 12. Self-inferencing property for a reflective field modification, deduced from the null argument and the dynamic type of the value argument at a set() call site. that the target field (to be modified in line 290) is static (from null) and its declared type must be java.lang.String or one of its supertypes (from the type of value). Definition 2.4 (Self-Inferencing Property). For each reflective-action call site, its self-inferencing property comprises the information that can be used to infer its reflective targets, which consists of (1) all the information of its arguments (including receiver object), namely the number of arguments, their types, and (2) the possible downcasts on its returned values, and (3) the possible string values statically resolved at its corresponding class-retrieving and member-retrieving call sites. We argue that the self-inferencing property is inherent in most Java reflection code due to the characteristics of object-oriented programming and the Java reflection API. For example, the declared type of the object reflectively returned by get() and invoke() or created by newInstance() is always java.lang.Object. Therefore, the returned object must be first cast to a specific type before it is used as a regular object, except when its dynamic type is java.lang.Object or it will be used only as an receiver for the methods inherited from java.lang.Object; otherwise, the compilation would fail. As another example, the descriptor of a target method reflectively called at invoke() must be consistent with what is specified by its second argument (e.g., parameters in line 175 of Figure 10); otherwise, exceptions would be thrown at runtime. These constraints should be exploited to enable resolving reflection in a disciplined way. The self-inferencing property not only helps resolve reflective calls more effectively when the values of string arguments are partially known (e.g., when either a class name or a member name is known), but also provides an opportunity to resolve some reflective calls even if the string values are fully unknown. For example, in some Android apps, class and method names for reflective calls are encrypted for benign or malicious obfuscation, which “makes it impossible for any static analysis to recover the reflective call” [48]. However, this appears to be too pessimistic in our setting, because, in addition to the string values, some other self-inferencing hints are possibly available to facilitate reflection resolution. For example, given (A)invoke(o, {...}), the class type of the target method can be inferred from the dynamic type of o (by pointer analysis), and the declared return type and descriptor of the target method can also be deduced from A and {...}, respectively, as discussed above. ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019