7:6 Yue Li,Tian Tan,and Jingling Xue Intercession:the ability of a program to modify its own execution state or alter its own interpretation or meaning. Providing full reflective abilities as shown above is challenging in practice,as this will introduce both implementation complexities and performance problems [10].Thus,in modern programming languages like Java,reflective abilities are only partially supported [6,19]. 2.1.3 Java Reflection.Java reflection supports introspection and very limited intercession;in particular,an introspection step is usually followed by behaviour changes such as object creation, method invocation and attribute manipulation [9,19].Note that some other researchers hold a different view that Java reflection does not support intercession [6,16],as they adopt a more strict definition of intercession,which implies the ability to modify the self-representation of a program. Despite its limited reflective abilities,Java reflection is able to allow programmers to break the constraints of staticity and encapsulation,enabling the program to adapt to dynamically changing runtime environments.As a result,Java reflection has been widely used in real-world Java applications to facilitate flexibly different programming tasks,such as reasoning about control (i.e.,about which computations to pursue next)[19],interfacing (e.g.,interaction with GUIs or database systems)[21,46],and self-activation (e.g.,through monitors)[13]. Java reflection does not have a reify operation as described in Section 2.1.1(Figure 2(b))to turn the basic(running)system(including stack frames)into a representation(data structure)that is passed to a metasystem.Instead,a kind of metarepresentation,based on metaobjects,exists when the system starts running and persists throughout the execution of the system[19]. A metaobject is like the reflection in a mirror:one can adjust one's smile(behaviour changes)by looking at oneself in a mirror(introspection).In Section 2.2,we will look at how Java reflection uses metaobjects and its API to facilitate reflective programming. 1 Aa new A(); 2 String cName,mName,fName =... 3 class clz Class.forName(cName); 4 Object obj clz.newInstance(); 5 Method mtd clz.getDeclaredMethod(mName,A.class); 6 Object 1 mtd.invoke(obj,a); 7 Field fld clz.getField(fName); 8 x r (X)fld.get(a); 9 fld.set(null,a); Fig.3.An example of reflection usage in Java. 2.2 Interface We first use a toy example to illustrate some common uses of the Java reflection API(Section 2.2.1). We then delve into the details of its core methods,which are relevant to (and thus should be handled by)any reflection analysis (Section 2.2.2). 2.2.1 An Example.There are two kinds of metaobjects:Class objects and member objects.In Java reflection,one always starts with a Class object and then obtain its member objects(e.g., Method and Field objects)from the Class object by calling its corresponding accessor methods (e.g.,getMethod()and getField()). ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019
7:6 Yue Li, Tian Tan, and Jingling Xue • Intercession: the ability of a program to modify its own execution state or alter its own interpretation or meaning. Providing full reflective abilities as shown above is challenging in practice, as this will introduce both implementation complexities and performance problems [10]. Thus, in modern programming languages like Java, reflective abilities are only partially supported [6, 19]. 2.1.3 Java Reflection. Java reflection supports introspection and very limited intercession; in particular, an introspection step is usually followed by behaviour changes such as object creation, method invocation and attribute manipulation [9, 19]. Note that some other researchers hold a different view that Java reflection does not support intercession [6, 16], as they adopt a more strict definition of intercession, which implies the ability to modify the self-representation of a program. Despite its limited reflective abilities, Java reflection is able to allow programmers to break the constraints of staticity and encapsulation, enabling the program to adapt to dynamically changing runtime environments. As a result, Java reflection has been widely used in real-world Java applications to facilitate flexibly different programming tasks, such as reasoning about control (i.e., about which computations to pursue next) [19], interfacing (e.g., interaction with GUIs or database systems) [21, 46], and self-activation (e.g., through monitors) [13]. Java reflection does not have a reify operation as described in Section 2.1.1 (Figure 2(b)) to turn the basic (running) system (including stack frames) into a representation (data structure) that is passed to a metasystem. Instead, a kind of metarepresentation, based on metaobjects, exists when the system starts running and persists throughout the execution of the system [19]. A metaobject is like the reflection in a mirror: one can adjust one’s smile (behaviour changes) by looking at oneself in a mirror (introspection). In Section 2.2, we will look at how Java reflection uses metaobjects and its API to facilitate reflective programming. 1 A a = new A(); 2 String cName, mName, fName = ...; 3 Class clz = Class.forName(cName); 4 Object obj = clz.newInstance(); 5 Method mtd = clz.getDeclaredMethod(mName, A.class); 6 Object l = mtd.invoke(obj, a); 7 Field fld = clz.getField(fName); 8 X r = (X)fld.get(a); 9 fld.set(null, a); Fig. 3. An example of reflection usage in Java. 2.2 Interface We first use a toy example to illustrate some common uses of the Java reflection API (Section 2.2.1). We then delve into the details of its core methods, which are relevant to (and thus should be handled by) any reflection analysis (Section 2.2.2). 2.2.1 An Example. There are two kinds of metaobjects: Class objects and member objects. In Java reflection, one always starts with a Class object and then obtain its member objects (e.g., Method and Field objects) from the Class object by calling its corresponding accessor methods (e.g., getMethod() and getField()). ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019
Understanding and Analyzing Java Reflection 7:7 Class::newInstance Class::getDeclaredConstructor Constructor object Class::getConstructor Constructor::newInstance Class::getDeclaredConstructors Class object class:getConstructors Class:forName Class:getDeclaredMethod Method object ClassLoader::loadClass Class:getMethod Object::getclass Class::getDeclaredMethods Method::invoke Others .class Class::getMethods Field object Class:getDeclaredField Class::getPield Field::get Class:getDeclaredFields Field::set Class::getFields Proxy:newProxyInstance Array::newInstance Class object flows to (as a receiver object) Class-Retrieving Methods Array object Member object flows to(as a receiver object)Member-Retrieving Methods Class/Array object flows to (as an argument)Reflective-Action Methods Array::get Array::set Fig.4.Overview of core Java reflection APl. In Figure 3,the metaobjects clz,mtd and fld are instances of the metaobject classes Class, Method and Field,respectively.Constructor can be seen as Method except that the method name "<init>"is implicit.Class allows an object to be created reflectively by calling newInstance(). As shown in line 4,the dynamic type of obj is the class(type)represented by clz(specified by cName).In addition,Class provides accessor methods such as getDeclaredMethod()in line 5 and getField()in line 7 to allow the member metaobjects (e.g.,of Method and Field)related to a Class object to be introspected.With dynamic invocation,a Method object can be commanded to invoke the method that it represents(line 6).Similarly,a Field object can be commanded to access or modify the field that it represents(lines 8 and 9). 2.2.2 Core Java Reflection APl.In reflection analysis,we are concerned with reasoning about how reflection affects the control and data flow information in the program.For example,if a target method(say m)that is reflectively invoked in line 6 in Figure 3 cannot be resolved statically,the call graph edge from this call site to method m(control flow)and the values passed interprocedurally from obj and a to this and the parameter of m(data flow),respectively,will be missing.Therefore,we should focus on the part of the Java reflection API that affects a pointer analysis,a fundamental analysis that statically resolves the control and data flow information in a Pr0gram[27,30-32,38,41,42,51,52,60-62]. It is thus sufficient to consider only the pointer-affecting methods in the Java reflection API.We can divide such reflective methods into three categories(Figure 4): We summarize and explain the core reflection API(25 methods)that is critical to static analysis.A more complete reflection API list(181 methods)is given in [26]without explanations though. ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019
Understanding and Analyzing Java Reflection 7:7 Class::forName Class object flows to (as a receiver object) Class-Retrieving Methods Member-Retrieving Methods Reflective-Action Methods .class Object::getClass ClassLoader::loadClass Class::getMethod Class::getDeclaredMethods Class::getMethods Class::getField Class::getDeclaredField Class::getDeclaredFields Class::getFields Class::getConstructor Class::getDeclaredConstructor Class::getDeclaredConstructors Class::getConstructors Constructor::newInstance Method::invoke Field::get Field::set Class::newInstance Proxy::newProxyInstance Array::newInstance Array::get Array::set Class Object Constructor Object Method Object Field Object Array Object Member object flows to (as a receiver object) Class/Array object flows to (as an argument) Others Class::getDeclaredMethod Fig. 4. Overview of core Java reflection API.1 In Figure 3, the metaobjects clz, mtd and fld are instances of the metaobject classes Class, Method and Field, respectively. Constructor can be seen as Method except that the method name “<init>” is implicit. Class allows an object to be created reflectively by calling newInstance(). As shown in line 4, the dynamic type of obj is the class (type) represented by clz (specified by cName). In addition, Class provides accessor methods such as getDeclaredMethod() in line 5 and getField() in line 7 to allow the member metaobjects (e.g., of Method and Field) related to a Class object to be introspected. With dynamic invocation, a Method object can be commanded to invoke the method that it represents (line 6). Similarly, a Field object can be commanded to access or modify the field that it represents (lines 8 and 9). 2.2.2 Core Java Reflection API. In reflection analysis, we are concerned with reasoning about how reflection affects the control and data flow information in the program. For example, if a target method (say m) that is reflectively invoked in line 6 in Figure 3 cannot be resolved statically, the call graph edge from this call site to method m (control flow) and the values passed interprocedurally from obj and a to this and the parameter of m (data flow), respectively, will be missing. Therefore, we should focus on the part of the Java reflection API that affects a pointer analysis, a fundamental analysis that statically resolves the control and data flow information in a program [27, 30–32, 38, 41, 42, 51, 52, 60–62]. It is thus sufficient to consider only the pointer-affecting methods in the Java reflection API. We can divide such reflective methods into three categories (Figure 4): 1We summarize and explain the core reflection API (25 methods) that is critical to static analysis. A more complete reflection API list (181 methods) is given in [26] without explanations though. ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019
7:8 Yue Li,Tian Tan,and Jingling Xue class-retrieving methods,which create Class objects,e.g.,forName()in line 3 in Figure 3. member-retrieving methods,which introspect and retrieve member metaobjects,i.e.,Method (Constructor)and Field objects from a Class object,e.g.,getDeclaredMethod()in line 5 and getField()in line 7 in Figure 3. reflective-action methods,which affect the pointer information in the program reflectively, e.g.,newInstance(),invoke(),get()and set()in lines 4,6,8 and 9 in Figure 3 for creating an object,invoking a method,accessing and modifying a field,respectively. Class-Retrieving Methods.Everything in Java reflection begins with Class objects and they are returned by calling class-retrieving methods.There are many class-retrieving methods in the Java reflection API.In Figure 4,only the four most widely used ones are listed explicitly Note that forName()(loadclass())returns a Class object representing a class that is specified by the value of its string argument.The class object returned by o.getclass()and A.class represents the dynamic type(class)of o and A,respectively. Member-Retrieving Methods.Class provides a number of accessor methods for retrieving its member metaobjects,i.e.,the Method(Constructor)and Field objects.In addition,these member metaobjects can be used to introspect the methods,constructors and fields in their target class. Formally,these accessor methods are referred to here as the member-retrieving methods. As shown in Figure 4,for each kind of member metaobjects,there are four member-retrieving methods.We take a Method object as an example to illustrate these methods,whose receiver objects are the Class objects returned by the class-retrieving methods. getDeclaredMethod(String,Class[])returns a Method object that represents a declared method of the target Class object with the name(formal parameter types)specified by the first (second)parameter (line 5 in Figure 3). getMethod(String,Class[])is similar to getDeclaredMethod(String,Class[])ex- cept that the returned Method object is public(either declared or inherited).If the target Class does not have a matching method,then its superclasses are searched first recursively (bottom-up)before its interfaces(implemented). getDeclaredMethods()returns an array of Method objects representing all the methods declared in the target Class object. getMethods()is similar to getDeclaredMethods()except that all the public methods(either declared or inherited)in the target Class object are returned. Reflective-Action Methods.As shown in Figure 4,a total of nine reflective-action methods that can possibly modify or use(as their side effects)the pointer information in a program are listed. Accordingly,Table 1 explains how these methods affect the pointer information by giving their side effects on the pointer analysis. In Figure 4,the first five reflective-action methods use four kinds of metaobjects as their receiver objects while the last four methods use Class or Array objects as their arguments.Below we briefly examine them in the order given in Table 1. The side effect of newInstance()is allocating an object with the type specified by its metaobject clz or ctor(say A)and initializing it via a constructor of A,which is the default constructor in the case of Class:newInstance()and the constructor specified explicitly in the case of Constructor:newInstance(). The side effect of invoke()is a virtual call when the first argument of invoke(),say o,is not null.The receiver object is o as shown in the "Side Effect"column in Table 1.When o is null,invoke()should be a static call. ACM Trans.Softw.Eng.Methodol,Vol.28,No.2,Article 7.Publication date:February 2019
7:8 Yue Li, Tian Tan, and Jingling Xue • class-retrieving methods, which create Class objects, e.g., forName() in line 3 in Figure 3. • member-retrieving methods, which introspect and retrieve member metaobjects, i.e., Method (Constructor) and Field objects from a Class object, e.g., getDeclaredMethod() in line 5 and getField() in line 7 in Figure 3. • reflective-action methods, which affect the pointer information in the program reflectively, e.g., newInstance(), invoke(), get() and set() in lines 4, 6, 8 and 9 in Figure 3 for creating an object, invoking a method, accessing and modifying a field, respectively. Class-Retrieving Methods. Everything in Java reflection begins with Class objects and they are returned by calling class-retrieving methods. There are many class-retrieving methods in the Java reflection API. In Figure 4, only the four most widely used ones are listed explicitly. Note that forName() (loadClass()) returns a Class object representing a class that is specified by the value of its string argument. The Class object returned by o.getClass() and A.class represents the dynamic type (class) of o and A, respectively. Member-Retrieving Methods. Class provides a number of accessor methods for retrieving its member metaobjects, i.e., the Method (Constructor) and Field objects. In addition, these member metaobjects can be used to introspect the methods, constructors and fields in their target class. Formally, these accessor methods are referred to here as the member-retrieving methods. As shown in Figure 4, for each kind of member metaobjects, there are four member-retrieving methods. We take a Method object as an example to illustrate these methods, whose receiver objects are the Class objects returned by the class-retrieving methods. • getDeclaredMethod(String, Class[]) returns a Method object that represents a declared method of the target Class object with the name (formal parameter types) specified by the first (second) parameter (line 5 in Figure 3). • getMethod(String, Class[]) is similar to getDeclaredMethod(String, Class[]) except that the returned Method object is public (either declared or inherited). If the target Class does not have a matching method, then its superclasses are searched first recursively (bottom-up) before its interfaces (implemented). • getDeclaredMethods() returns an array of Method objects representing all the methods declared in the target Class object. • getMethods() is similar to getDeclaredMethods() except that all the public methods (either declared or inherited) in the target Class object are returned. Reflective-Action Methods. As shown in Figure 4, a total of nine reflective-action methods that can possibly modify or use (as their side effects) the pointer information in a program are listed. Accordingly, Table 1 explains how these methods affect the pointer information by giving their side effects on the pointer analysis. In Figure 4, the first five reflective-action methods use four kinds of metaobjects as their receiver objects while the last four methods use Class or Array objects as their arguments. Below we briefly examine them in the order given in Table 1. • The side effect of newInstance() is allocating an object with the type specified by its metaobject clz or ctor (say A) and initializing it via a constructor of A, which is the default constructor in the case of Class::newInstance() and the constructor specified explicitly in the case of Constructor::newInstance(). • The side effect of invoke() is a virtual call when the first argument of invoke(), say o, is not null. The receiver object is o as shown in the “Side Effect” column in Table 1. When o is null, invoke() should be a static call. ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019
Understanding and Analyzing Java Reflection 7:9 Table 1.Nine reflective-action methods and their side effects on the pointer analysis,assuming that the target class of clz and ctor is A,the target method of mtd is m and the target field of fld is f. Simplified Method Calling Scenario Side Effect Class::newInstance o=clz.newInstance( o=new A() Constructor::newInstance o ctor.newInstance(farg1,.) o new A(arg1,...) Method::invoke a mtdinvoke(o,farg1,...) a=o.m(arg1,.) Field:get a fldget(o) a=o.f Field::set fld.set(o,a) o.f=a Proxy:newProxyInstance o Proxy.newProxyInstance(...) o=new Proxy$*(.) Array::newInstance o Array.newInstance(clz,size) o=new A[size] Array::get a=Array.get(o,i) a=o[i] Array::set Array.set(o,i,a) o[)=a The side effects of get()and set()are retrieving (loading)and modifying (storing)the value of a instance field,respectively,when their first argument,say o,is not null;otherwise, they are operating on a static field. The side effect of newProxyInstance()is creating an object of a proxy class Proxy$*,and this proxy class is generated dynamically according to its arguments(containing a Class object).Proxy.newProxyInstance()can be analyzed according to its semantics.A call to this method returns a Proxy object,which has an associated invocation handler object that implements the InvocationHandler interface.A method invocation on a Proxy object through one of its Proxy interfaces will be dispatched to the invoke()method of the object's invocation handler. The side effect of Array.newInstance()is creating an array (object)with the compo- nent type represented by the Class object(e.g.,clz in Table 1)used as its first argument. Array.get()and Array.set()are retrieving and modifying an index element in the array object specified as their first argument,respectively. 2.3 Reflection Usage The Java reflection API is rich and complex.We have conducted an empirical study to understand reflection usage in practice in order to guide the design and implementation of a sophisticated reflection analysis described in this paper.In this section,we first list the focus questions in Section 2.3.1,then describe the experimental setup in Section 2.3.2,and finally,present the study results in Section 2.3.3. 2.3.1 Focus Questions.We address the following seven focus questions in order to understand how Java reflection is used in the real world. .Q1.Existing reflection analyses resolve reflection by analyzing statically the string arguments of class-retrieving and member-retrieving method calls.How often are these strings constants ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019
Understanding and Analyzing Java Reflection 7:9 Table 1. Nine reflective-action methods and their side effects on the pointer analysis, assuming that the target class of clz and ctor is A, the target method of mtd is m and the target field of fld is f. Simplified Method Calling Scenario Side Effect Class::newInstance o = clz.newInstance() o = new A() Constructor::newInstance o = ctor.newInstance({arg1, ...}) o = new A(arg1, ...) Method::invoke a = mtd.invoke(o, {arg1, ...}) a = o.m(arg1, ...) Field::get a = fld.get(o) a = o.f Field::set fld.set(o, a) o.f = a Proxy::newProxyInstance o = Proxy.newProxyInstance(...) o = new Proxy$*(...) Array::newInstance o = Array.newInstance(clz, size) o = new A[size] Array::get a = Array.get(o, i) a = o[i] Array::set Array.set(o, i, a) o[i] = a • The side effects of get() and set() are retrieving (loading) and modifying (storing) the value of a instance field, respectively, when their first argument, say o, is not null; otherwise, they are operating on a static field. • The side effect of newProxyInstance() is creating an object of a proxy class Proxy$*, and this proxy class is generated dynamically according to its arguments (containing a Class object). Proxy.newProxyInstance() can be analyzed according to its semantics. A call to this method returns a Proxy object, which has an associated invocation handler object that implements the InvocationHandler interface. A method invocation on a Proxy object through one of its Proxy interfaces will be dispatched to the invoke() method of the object’s invocation handler. • The side effect of Array.newInstance() is creating an array (object) with the component type represented by the Class object (e.g., clz in Table 1) used as its first argument. Array.get() and Array.set() are retrieving and modifying an index element in the array object specified as their first argument, respectively. 2.3 Reflection Usage The Java reflection API is rich and complex. We have conducted an empirical study to understand reflection usage in practice in order to guide the design and implementation of a sophisticated reflection analysis described in this paper. In this section, we first list the focus questions in Section 2.3.1, then describe the experimental setup in Section 2.3.2, and finally, present the study results in Section 2.3.3. 2.3.1 Focus Questions. We address the following seven focus questions in order to understand how Java reflection is used in the real world. • Q1. Existing reflection analyses resolve reflection by analyzing statically the string arguments of class-retrieving and member-retrieving method calls. How often are these strings constants ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019
7:10 Yue Li,Tian Tan,and Jingling Xue and how often can non-constant strings be resolved by a simple string analysis that models string operations such as“+”and append()? Q2.Existing reflection analyses ignore the member-retrieving methods that return an array of member metaobjects.Is it necessary to handle such methods? .Q3.Existing reflection analyses usually treat reflective method calls and field accesses as being non-static.Does this treatment work well in real-world programs?Specifically,how often are static reflective targets used in reflective code? .Q4.In [38],intraprocedural post-dominating cast operations are leveraged to resolve newInstance() when its class type is unknown.This approach is still adopted by many reflection analysis tools.Does it generally work in practice? .Q5.The Java reflection API contains many class-retrieving methods for returning Class objects.Which ones should be focused on by an effective reflection analysis? .Q6.The core part of reflection analysis is to resolve all the nine reflective-action methods (Table 1)effectively.What are the reflective-action methods that are most widely used and how are the remaining ones used in terms of their relative frequencies? Q7.What are new insights on handling Java reflection(from this paper)? 2.3.2 Experimental Setup.We have selected a set of 16 representative Java programs,including three popular desktop applications,javac-1.7.0,jEdit-5.1.0 and Eclipse-4.2.2(denoted Eclipse4),two popular server applications,Jetty-9.0.5 and Tomcat-7.0.42,and all eleven DaCapo benchmarks(2006-10-MR2)[3].Note that the DaCapo benchmark suite includes an older version of Eclipse(version 3.1.2).We exclude its bloat benchmark since its application code is reflection-free.We consider lucene instead of luindex and lusearch separately since these two benchmarks are derived from lucene with the same reflection usage. We consider a total of 191 methods in the Java reflection API(version 1.6),including the ones mainly from package java.lang.reflect and class java.lang.Class. We use Soor [63]to pinpoint the calls to reflection methods in the bytecode of a program. To understand the common reflection usage,we consider only the reflective calls found in the application classes and their dependent libraries but exclude the standard Java libraries.To in- crease the code coverage for the five applications considered,we include the jar files whose names contain the names of these applications(e.g.,*jetty*.jar for Jetty)and make them avail- able under the process-dir option supported by Soor.For Eclipse4,we use org.eclipse.core. runtime.adaptor.EclipseStarter to let Soor locate all the other jar files used. We manually inspect the reflection usage in a program in a demand-driven manner,starting from its reflective-action methods,assisted by Open Call Hierarchy in Eclipse,by following their backward slices.For a total of 609 reflective-action call sites examined,510 call sites for calling class-retrieving methods and 304 call sites for calling member-retrieving methods are tracked and studied.As a result,a total of 1,423 reflective call sites,together with some nearby statements,are examined in our study. 2.3.3 Results.Below we describe our seven findings on reflection usage as our answers to the seven focus questions listed in Section 2.3.1,respectively.We summarize our findings as individual remarks,which are expected to be helpful in guiding the development of practical reflection analysis techniques and tools in future research. O1.String Constants and String Manipulations.In class-retrieving methods,Class.forName( and loadclass()each have a String parameter to specify the target class.In member-retrieving methods,getDeclaredMethod(String,...and getMethod(String,...)each return a Method ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019
7:10 Yue Li, Tian Tan, and Jingling Xue and how often can non-constant strings be resolved by a simple string analysis that models string operations such as “+” and append()? • Q2. Existing reflection analyses ignore the member-retrieving methods that return an array of member metaobjects. Is it necessary to handle such methods? • Q3. Existing reflection analyses usually treat reflective method calls and field accesses as being non-static. Does this treatment work well in real-world programs? Specifically, how often are static reflective targets used in reflective code? • Q4. In [38], intraprocedural post-dominating cast operations are leveraged to resolve newInstance() when its class type is unknown. This approach is still adopted by many reflection analysis tools. Does it generally work in practice? • Q5. The Java reflection API contains many class-retrieving methods for returning Class objects. Which ones should be focused on by an effective reflection analysis? • Q6. The core part of reflection analysis is to resolve all the nine reflective-action methods (Table 1) effectively. What are the reflective-action methods that are most widely used and how are the remaining ones used in terms of their relative frequencies? • Q7. What are new insights on handling Java reflection (from this paper)? 2.3.2 Experimental Setup. We have selected a set of 16 representative Java programs, including three popular desktop applications, javac-1.7.0, jEdit-5.1.0 and Eclipse-4.2.2 (denoted Eclipse4), two popular server applications, Jetty-9.0.5 and Tomcat-7.0.42, and all eleven DaCapo benchmarks (2006-10-MR2) [3]. Note that the DaCapo benchmark suite includes an older version of Eclipse (version 3.1.2). We exclude its bloat benchmark since its application code is reflection-free. We consider lucene instead of luindex and lusearch separately since these two benchmarks are derived from lucene with the same reflection usage. We consider a total of 191 methods in the Java reflection API (version 1.6), including the ones mainly from package java.lang.reflect and class java.lang.Class. We use Soot [63] to pinpoint the calls to reflection methods in the bytecode of a program. To understand the common reflection usage, we consider only the reflective calls found in the application classes and their dependent libraries but exclude the standard Java libraries. To increase the code coverage for the five applications considered, we include the jar files whose names contain the names of these applications (e.g., *jetty*.jar for Jetty) and make them available under the process-dir option supported by Soot. For Eclipse4, we use org.eclipse.core. runtime.adaptor.EclipseStarter to let Soot locate all the other jar files used. We manually inspect the reflection usage in a program in a demand-driven manner, starting from its reflective-action methods, assisted by Open Call Hierarchy in Eclipse, by following their backward slices. For a total of 609 reflective-action call sites examined, 510 call sites for calling class-retrieving methods and 304 call sites for calling member-retrieving methods are tracked and studied. As a result, a total of 1,423 reflective call sites, together with some nearby statements, are examined in our study. 2.3.3 Results. Below we describe our seven findings on reflection usage as our answers to the seven focus questions listed in Section 2.3.1, respectively. We summarize our findings as individual remarks, which are expected to be helpful in guiding the development of practical reflection analysis techniques and tools in future research. Q1. String Constants and String Manipulations. In class-retrieving methods, Class.forName() and loadClass() each have a String parameter to specify the target class. In member-retrieving methods, getDeclaredMethod(String,...) and getMethod(String,...) each return a Method ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019