Understanding and Analyzing Java Reflection YUE LI',UNSW Sydney,Australia TIAN TAN',UNSW Sydney,Australia JINGLING XUE,UNSW Sydney,Australia Java reflection has been widely used in a variety of applications and frameworks.It allows a software system to inspect and change the behaviour of its classes,interfaces,methods and fields at runtime,enabling the software to adapt to dynamically changing runtime environments.However,this dynamic language feature imposes significant challenges to static analysis,because the behaviour of reflection-rich software is logically complex and statically hard to predict.As a result,existing static analysis tools either ignore reflection or handle it partially,resulting in missed,important behaviours,i.e.,unsound results.Therefore,improving or even achieving soundness in(static)reflection analysis-an analysis that infers statically the behaviour of reflective code-will provide significant benefits to many analysis clients,such as bug detectors,security analyzers and program verifiers. In this paper,we provide a comprehensive understanding of Java reflection through examining its underlying concept,API and real-world usage,and,building on this,we introduce a new static approach to resolving Java reflection effectively in practice.We have implemented our reflection analysis in an open-source tool,called SoLAR,and evaluated its effectiveness extensively with large Java programs and libraries.Our experimental results demonstrate that SoLAR is able to(1)resolve reflection more soundly than the state-of-the-art reflection analyses:(2)automatically and accurately identify the parts of the program where reflection is resolved unsoundly or imprecisely:and(3)guide users to iteratively refine the analysis results by using lightweight annotations until their specific requirements are satisfied. CCS Concepts:·Theory of computation→Program analysis;:·Software and its engineering→ Object oriented languages. Additional Key Words and Phrases:Java reflection,static analysis,points-to analysis ACM Reference Format: Yue Li,Tian Tan,and Jingling Xue.2019.Understanding and Analyzing Java Reflection.ACM Trans.Softw. Eng.Methodol.28,2,Article 7(February 2019),51 pages.https://doi.org/10.1145/nnnnnnn.nnnnnnn 1 INTRODUCTION Java reflection allows a software system to inspect and change the behaviour of its classes,interfaces, methods and fields at runtime,enabling the software to adapt to dynamically changing runtime environments.This dynamic language feature eases the development and maintenance of Java programs in many programming tasks by,for example,facilitating their flexible integration with the third-party code and their main behaviours to be configured according to a deployed runtime "This work was mostly done while these authors were at UNSW Sydney.Both authors are now affiliated with Aarhus University,Denmark. Authors'addresses:Yue Li,Aarhus University,Denmark,yueli@cs.au.dk;Tian Tan,Aarhus University,Denmark, tiantan@cs.au.dk;Jingling Xue,UNSW Sydney,Australia,jingling@cs.au.dk. Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page.Copyrights for components of this work owned by others than ACM must be honored. Abstracting with credit is permitted.To copy otherwise,or republish,to post on servers or to redistribute to lists,requires prior specific permission and/or a fee.Request permissions from permissions@acm.org. 2019 Association for Computing Machinery. 1049-331X/2019/02-ART7$15.00 https://doi.org/10.1145/nnnnnnn.nnnnnnn ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019
7 Understanding and Analyzing Java Reflection YUE LI∗ , UNSW Sydney, Australia TIAN TAN∗ , UNSW Sydney, Australia JINGLING XUE, UNSW Sydney, Australia Java reflection has been widely used in a variety of applications and frameworks. It allows a software system to inspect and change the behaviour of its classes, interfaces, methods and fields at runtime, enabling the software to adapt to dynamically changing runtime environments. However, this dynamic language feature imposes significant challenges to static analysis, because the behaviour of reflection-rich software is logically complex and statically hard to predict. As a result, existing static analysis tools either ignore reflection or handle it partially, resulting in missed, important behaviours, i.e., unsound results. Therefore, improving or even achieving soundness in (static) reflection analysis—an analysis that infers statically the behaviour of reflective code—will provide significant benefits to many analysis clients, such as bug detectors, security analyzers and program verifiers. In this paper, we provide a comprehensive understanding of Java reflection through examining its underlying concept, API and real-world usage, and, building on this, we introduce a new static approach to resolving Java reflection effectively in practice. We have implemented our reflection analysis in an open-source tool, called Solar, and evaluated its effectiveness extensively with large Java programs and libraries. Our experimental results demonstrate that Solar is able to (1) resolve reflection more soundly than the state-of-the-art reflection analyses; (2) automatically and accurately identify the parts of the program where reflection is resolved unsoundly or imprecisely; and (3) guide users to iteratively refine the analysis results by using lightweight annotations until their specific requirements are satisfied. CCS Concepts: • Theory of computation → Program analysis; • Software and its engineering → Object oriented languages. Additional Key Words and Phrases: Java reflection, static analysis, points-to analysis ACM Reference Format: Yue Li, Tian Tan, and Jingling Xue. 2019. Understanding and Analyzing Java Reflection. ACM Trans. Softw. Eng. Methodol. 28, 2, Article 7 (February 2019), 51 pages. https://doi.org/10.1145/nnnnnnn.nnnnnnn 1 INTRODUCTION Java reflection allows a software system to inspect and change the behaviour of its classes, interfaces, methods and fields at runtime, enabling the software to adapt to dynamically changing runtime environments. This dynamic language feature eases the development and maintenance of Java programs in many programming tasks by, for example, facilitating their flexible integration with the third-party code and their main behaviours to be configured according to a deployed runtime ∗This work was mostly done while these authors were at UNSW Sydney. Both authors are now affiliated with Aarhus University, Denmark. Authors’ addresses: Yue Li, Aarhus University, Denmark, yueli@cs.au.dk; Tian Tan, Aarhus University, Denmark, tiantan@cs.au.dk; Jingling Xue, UNSW Sydney, Australia, jingling@cs.au.dk. Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyrights for components of this work owned by others than ACM must be honored. Abstracting with credit is permitted. To copy otherwise, or republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Request permissions from permissions@acm.org. © 2019 Association for Computing Machinery. 1049-331X/2019/02-ART7 $15.00 https://doi.org/10.1145/nnnnnnn.nnnnnnn ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019
7:2 Yue Li,Tian Tan,and Jingling Xue environment in a decoupled way.Due to such advantages,reflection has been widely used in a variety of Java applications and frameworks [32,69]. Static analysis is widely recognized as a fundamental tool for bug detection [17,43],security vulnerability analysis [1,36],compiler optimization [14,59],program verification [4,12],and program debugging and understanding [34,58].However,when applying static analysis to Java programs,reflection poses a major obstacle [32,33,38,51].If the behavior of reflective code is not resolved well,much of the codebase will be rendered invisible for static analysis,resulting in missed,important behaviours,i.e.,unsound analysis results [37].Therefore,improving or even achieving soundness in (static)reflection analysis-an analysis that infers statically the behavior of reflective code-will provide significant benefits to all the client analyses as just mentioned above. 1.1 Challenges Developing effective reflection analysis for real-world programs remains a hard problem,widely acknowledged by the static analysis community [37]: "Reflection usage and the size of libraries/frameworks make it very difficult to scale points-to analysis to modern Java programs."[64]; "Reflection makes it difficult to analyze statically."[48]; "In our experience [18],the largest challenge to analyzing Android apps is their use of reflection.”[2]: "Static analysis of object-oriented code is an exciting,ongoing and challenging research area,made especially challenging by dynamic language features,a.k.a.reflection."[26]. There are three reasons on why it is hard to untangle this knotty problem: The Java reflection API is large and its common uses in Java programs are complex.It remains unclear how an analysis should focus on its effort on analyzing which of its reflection methods in order to achieve some analysis results as desired. The dynamic behaviours of reflective calls are mainly specified by their string arguments, which are usually unknown statically(e.g.,with some string values being encrypted,read from configuration files,or retrieved from the Internet). The reflective code in a Java program cannot be analyzed alone in isolation.To resolve reflective calls adequately,a reflection analysis often works inter-dependently with a pointer analysis [32,33,38,50,51],with each being both the producer and consumer of the other. When some reflective calls are not yet resolved,the pointer information that is currently available can be over-or under-approximate.Care must be taken to ensure that the reflection analysis helps increase soundness(coverage)while still maintaining sufficient precision for the pointer analysis.Otherwise,the combined analysis would be unscalable for large programs. As a result,most of the papers on static analysis for object-oriented languages,like Java,treat reflection orthogonally (often without even mentioning its existence).Existing static analysis tools either ignore reflection or handle it partially and ineffectively. 1.2 Previous Approaches Initially,reflection analysis mainly relies on string analysis,especially when the string arguments to reflective calls are string constants,to resolve reflective targets,i.e.,methods or fields reflectively accessed.Currently,this mainstream approach is still adopted by many static analysis tools for Java, such as SooT,WALA,CHORD and DooP.However,as described in Section 1.1,string analysis will fail in many situations where string arguments are unknown(Figure 5),resulting in limited soundness ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019
7:2 Yue Li, Tian Tan, and Jingling Xue environment in a decoupled way. Due to such advantages, reflection has been widely used in a variety of Java applications and frameworks [32, 69]. Static analysis is widely recognized as a fundamental tool for bug detection [17, 43], security vulnerability analysis [1, 36], compiler optimization [14, 59], program verification [4, 12], and program debugging and understanding [34, 58]. However, when applying static analysis to Java programs, reflection poses a major obstacle [32, 33, 38, 51]. If the behavior of reflective code is not resolved well, much of the codebase will be rendered invisible for static analysis, resulting in missed, important behaviours, i.e., unsound analysis results [37]. Therefore, improving or even achieving soundness in (static) reflection analysis—an analysis that infers statically the behavior of reflective code—will provide significant benefits to all the client analyses as just mentioned above. 1.1 Challenges Developing effective reflection analysis for real-world programs remains a hard problem, widely acknowledged by the static analysis community [37]: “Reflection usage and the size of libraries/frameworks make it very difficult to scale points-to analysis to modern Java programs.” [64]; “Reflection makes it difficult to analyze statically.” [48]; “In our experience [18], the largest challenge to analyzing Android apps is their use of reflection ...” [2]; “Static analysis of object-oriented code is an exciting, ongoing and challenging research area, made especially challenging by dynamic language features, a.k.a. reflection.” [26]. There are three reasons on why it is hard to untangle this knotty problem: • The Java reflection API is large and its common uses in Java programs are complex. It remains unclear how an analysis should focus on its effort on analyzing which of its reflection methods in order to achieve some analysis results as desired. • The dynamic behaviours of reflective calls are mainly specified by their string arguments, which are usually unknown statically (e.g., with some string values being encrypted, read from configuration files, or retrieved from the Internet). • The reflective code in a Java program cannot be analyzed alone in isolation. To resolve reflective calls adequately, a reflection analysis often works inter-dependently with a pointer analysis [32, 33, 38, 50, 51], with each being both the producer and consumer of the other. When some reflective calls are not yet resolved, the pointer information that is currently available can be over- or under-approximate. Care must be taken to ensure that the reflection analysis helps increase soundness (coverage) while still maintaining sufficient precision for the pointer analysis. Otherwise, the combined analysis would be unscalable for large programs. As a result, most of the papers on static analysis for object-oriented languages, like Java, treat reflection orthogonally (often without even mentioning its existence). Existing static analysis tools either ignore reflection or handle it partially and ineffectively. 1.2 Previous Approaches Initially, reflection analysis mainly relies on string analysis, especially when the string arguments to reflective calls are string constants, to resolve reflective targets, i.e., methods or fields reflectively accessed. Currently, this mainstream approach is still adopted by many static analysis tools for Java, such as Soot, Wala, Chord and Doop. However, as described in Section 1.1, string analysis will fail in many situations where string arguments are unknown (Figure 5), resulting in limited soundness ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019
Understanding and Analyzing Java Reflection 7:3 and precision.As a static analysis,a(more)sound reflection analysis is one that allows (more) true reflective targets(i.e.,targets that are actually accessed at runtime)to be resolved statically. In practice,any reflection analysis must inevitably make a trade-off among soundness,precision, scalability,and(sometimes)automation. In addition,existing reflection analyses [2,8,20,22,28,32,35,38,51,68]cannot answer two critical questions that are raised naturally,in practice:Q(1)how sound is a given reflection analysis and Q(2)which reflective calls are resolved unsoundly or imprecisely?We argue for their importance as follows: If Q(1)is unanswered,users would be unsure (or lose confidence)about the effectiveness of the analysis results produced.For example,a bug detector that reports no bugs may actually miss many bugs if some reflective calls are resolved unsoundly. If Q(2)is unanswered,users would not have an opportunity to contribute in improving the precision and soundness of the analysis results,e.g.,by providing some user annotations.For some client analyses (e.g.,verification),soundness is required. 1.3 Contributions In this paper,we attempt to uncover the mysterious veil of Java reflection and change the informed opinion in the program analysis community about static reflection analysis:"Java reflection is a dynamic feature which is nearly impossible to handle effectively in static analysis".Specifically,we make the following contributions: We provide a comprehensive understanding of Java reflection through examining its under- lying concept (what it is),interface (how its API is designed),and real-world usage (how it is used in practice).As a result,we will provide the answers to several critical questions,which are somewhat related,including: What is reflection,why is it introduced in programming languages,and how is Java reflection derived from the basic reflection concept? Which methods of the Java reflection API should be analyzed carefully and how are they related,as the API is large and complex(with about 200 methods)? How is reflection used in real-world Java programs and what can we learn from its common uses?We have conducted a comprehensive study about reflection usage in a set of 16 representative Java programs by examining their 1,423 reflective call sites.We report 7 useful findings to enable the development of improved practical reflection analysis techniques and tools in future research. We introduce a new static analysis approach,called SoLAR (soundness-guided reflection analy- sis),to resolve Java reflection effectively in practice.As shown in Figure 1,SoLAR has three unique advantages compared with previous work: SoLAR is able to yield significantly more sound results than the state-of-the-art reflec- tion analysis.In addition,SoLAR allows its soundness to be reasoned about when some reasonable assumptions are met. SoLAR is able to accurately identify the parts of the program where reflection is analyzed unsoundly or imprecisely,making it possible for users to be aware of the effectiveness of their analysis results(as discussed in Section 1.2). -SoLAR provides a mechanism to guide users to iteratively refine the analysis results by adding lightweight annotations until their specific requirements are satisfied,enabling reflection to be analyzed in a controlled manner. ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019
Understanding and Analyzing Java Reflection 7:3 and precision. As a static analysis, a (more) sound reflection analysis is one that allows (more) true reflective targets (i.e., targets that are actually accessed at runtime) to be resolved statically. In practice, any reflection analysis must inevitably make a trade-off among soundness, precision, scalability, and (sometimes) automation. In addition, existing reflection analyses [2, 8, 20, 22, 28, 32, 35, 38, 51, 68] cannot answer two critical questions that are raised naturally, in practice: Q(1) how sound is a given reflection analysis and Q(2) which reflective calls are resolved unsoundly or imprecisely? We argue for their importance as follows: • If Q(1) is unanswered, users would be unsure (or lose confidence) about the effectiveness of the analysis results produced. For example, a bug detector that reports no bugs may actually miss many bugs if some reflective calls are resolved unsoundly. • If Q(2) is unanswered, users would not have an opportunity to contribute in improving the precision and soundness of the analysis results, e.g., by providing some user annotations. For some client analyses (e.g., verification), soundness is required. 1.3 Contributions In this paper, we attempt to uncover the mysterious veil of Java reflection and change the informed opinion in the program analysis community about static reflection analysis: “Java reflection is a dynamic feature which is nearly impossible to handle effectively in static analysis”. Specifically, we make the following contributions: • We provide a comprehensive understanding of Java reflection through examining its underlying concept (what it is), interface (how its API is designed), and real-world usage (how it is used in practice). As a result, we will provide the answers to several critical questions, which are somewhat related, including: – What is reflection, why is it introduced in programming languages, and how is Java reflection derived from the basic reflection concept? – Which methods of the Java reflection API should be analyzed carefully and how are they related, as the API is large and complex (with about 200 methods)? – How is reflection used in real-world Java programs and what can we learn from its common uses? We have conducted a comprehensive study about reflection usage in a set of 16 representative Java programs by examining their 1,423 reflective call sites. We report 7 useful findings to enable the development of improved practical reflection analysis techniques and tools in future research. • We introduce a new static analysis approach, called Solar (soundness-guided reflection analysis), to resolve Java reflection effectively in practice. As shown in Figure 1, Solar has three unique advantages compared with previous work: – Solar is able to yield significantly more sound results than the state-of-the-art reflection analysis. In addition, Solar allows its soundness to be reasoned about when some reasonable assumptions are met. – Solar is able to accurately identify the parts of the program where reflection is analyzed unsoundly or imprecisely, making it possible for users to be aware of the effectiveness of their analysis results (as discussed in Section 1.2). – Solar provides a mechanism to guide users to iteratively refine the analysis results by adding lightweight annotations until their specific requirements are satisfied, enabling reflection to be analyzed in a controlled manner. ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019
7:4 Yue Li,Tian Tan,and Jingling Xue ---2-.Unknown Soundness Boundary Achieved Soundness Known Soundness Boundary Identified Unsoundness (a)Previous Reflection Analysis (b)SoLAR:Soundness-Guided Reflection Analysis Fig.1.Reflection analysis:prior work vs.SoLAR. We have implemented SoLAR in Doop [8](a state-of-the-art pointer analysis tool for Java) and released it as an open-source tool.In particular,SoLAR can output its reflection analysis results with the format that is supported by Soor [63](a popular framework for analyzing Java and Android applications),allowing Soor's clients to use SoLAR's results directly. We conduct extensive experiments on evaluating SoLAR's effectiveness with large Java applications and libraries.Our experimental results provide convincing evidence on the ability of SoLAR in analyzing Java reflection effectively,in practice. 1.4 Organization The rest of this paper is organized as follows.We will start by providing a comprehensive under- standing of Java reflection in Section 2.Building on this understanding,we give an overview of SoLAR in Section 3 and introduce its underlying methodology in Section 4.Then,we formalize SoLAR in Section 5,describe its implementation in Section 6,and evaluate its effectiveness in Section 7.Finally,we discuss the related work in Section 8 and conclude in Section 9. 2 UNDERSTANDING JAVA REFLECTION Java reflection is a useful but complex language feature.To gain a deep understanding about Java reflection,we examine it in three steps.First,we describe what Java reflection is,why we need it,and how it is proposed(Section 2.1).Second,we explain how Java reflection is designed to be used,i.e,its API(Section 2.2).Finally,we investigate comprehensively how it has been used in real-world Java applications(Section 2.3).After reading this section,the readers are expected to develop a whole picture about the basic mechanism behind Java reflection,understand its core API design,and capture the key insights needed for developing practical reflection analysis tools. 2.1 Concept Reflection,which has long been studied in philosophy,represents one kind of human abilities for introspecting and learning their nature.Accordingly,a(non-human)object can also be endowed with the capability of such self-awareness.This arises naturally in artificial intelligence:"Here I am walking into a dark room.Since I cannot see anything,I should turn on the light".As explained in [54],"such thought fragment reveals a self-awareness of behaviour and state,one that leads to a ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019
7:4 Yue Li, Tian Tan, and Jingling Xue Previous Reflection Analysis ? (a) (b) SOLAR: Soundness-Guided Reflection Analysis Achieved Soundness Identified Unsoundness ? Unknown Soundness Boundary Known Soundness Boundary Fig. 1. Reflection analysis: prior work vs. Solar. • We have implemented Solar in Doop [8] (a state-of-the-art pointer analysis tool for Java) and released it as an open-source tool. In particular, Solar can output its reflection analysis results with the format that is supported by Soot [63] (a popular framework for analyzing Java and Android applications), allowing Soot’s clients to use Solar’s results directly. • We conduct extensive experiments on evaluating Solar’s effectiveness with large Java applications and libraries. Our experimental results provide convincing evidence on the ability of Solar in analyzing Java reflection effectively, in practice. 1.4 Organization The rest of this paper is organized as follows. We will start by providing a comprehensive understanding of Java reflection in Section 2. Building on this understanding, we give an overview of Solar in Section 3 and introduce its underlying methodology in Section 4. Then, we formalize Solar in Section 5, describe its implementation in Section 6, and evaluate its effectiveness in Section 7. Finally, we discuss the related work in Section 8 and conclude in Section 9. 2 UNDERSTANDING JAVA REFLECTION Java reflection is a useful but complex language feature. To gain a deep understanding about Java reflection, we examine it in three steps. First, we describe what Java reflection is, why we need it, and how it is proposed (Section 2.1). Second, we explain how Java reflection is designed to be used, i.e., its API (Section 2.2). Finally, we investigate comprehensively how it has been used in real-world Java applications (Section 2.3). After reading this section, the readers are expected to develop a whole picture about the basic mechanism behind Java reflection, understand its core API design, and capture the key insights needed for developing practical reflection analysis tools. 2.1 Concept Reflection, which has long been studied in philosophy, represents one kind of human abilities for introspecting and learning their nature. Accordingly, a (non-human) object can also be endowed with the capability of such self-awareness. This arises naturally in artificial intelligence: “Here I am walking into a dark room. Since I cannot see anything, I should turn on the light". As explained in [54], “such thought fragment reveals a self-awareness of behaviour and state, one that leads to a ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019
Understanding and Analyzing Java Reflection 7:5 Reify Metasystem ofS Reffect Computational The Domain Computational The Domain System S of S System S of S Answer Questions abou Answer Questions about andor and/or Support Actions in Support Actions in the Domain the Domain and S itself (a)Computational System and its Domain (b)Reflective System and its Domain Fig.2.Computational vs.reflective computational systems. change in that selfsame behaviour and state",which allows an object to examine itself and leverage the meta-level information to figure out what to do next. Similarly,when we enable programs to avail themselves of such reflective capabilities,reflective programs will also allow the programs to observe and modify properties of their own behaviour. Thus,let a program be self-aware-this is the basic motivation of the so-called computational reflection,which is also considered as the reflection used in the area of programming languages [15]. In the rest of this section,we will introduce what computational reflection is(Section 2.1.1),what reflective abilities it supports(Section 2.1.2),and how Java reflection is derived from it(Section 2.1.3). 2.1.1 Computational Reflection.Reflection,as a concept for computational systems,dates from Brian Smith's doctoral dissertation [53].Generally,as shown in Figure 2(a),a computational system is related to a domain and it answers questions about and/or support actions in the domain [39]. As described in [39],a computational system "incorporates internal structures representing the domain.These structures include data representing entities and relations in the domain and a program describing how these data may be manipulated". A computational system S is said to be also a reflective system,as shown in Figure 2(b),if the following two conditions are satisfied: First,the system S has its own representation,known as its self-representation or metasystem, in its domain as a kind of data to be examined and manipulated. Second,the system S and its representation are causally connected:a change to the repre- sentation implies a change to the system,and vice versa. The base system S should be reified into its representation before its metasystem can operate. Then the metasystem examines and manipulates its behaviour using the reified representation.If any changes are made by the metasystem,then the effects will also be reflected in the behavior of the corresponding base system. 2.1.2 Reflective Abilities.Generally,(computational)reflection is the ability of a program to examine and modify the structure and behavior of a program at runtime [23,40].Thus,it endows the program the capabilities of self-awareness and self-adapting.These two reflective abilities are known as introspection and intercession,respectively,and both require a reification mechanism to encode a program's execution state as data first [15]. Introspection:the ability of a program to observe,and consequently,reason about its own execution state. ACM Trans.Softw.Eng.Methodol.,Vol.28,No.2,Article 7.Publication date:February 2019
Understanding and Analyzing Java Reflection 7:5 Metasystem of S The Domain of S Computational System S Reify Reflect and/or Support Actions in Answer Questions about the Domain and S itself The Domain of S Computational System S and/or Support Actions in Answer Questions about the Domain (a) Computational System and its Domain (b) Reflective System and its Domain Fig. 2. Computational vs. reflective computational systems. change in that selfsame behaviour and state”, which allows an object to examine itself and leverage the meta-level information to figure out what to do next. Similarly, when we enable programs to avail themselves of such reflective capabilities, reflective programs will also allow the programs to observe and modify properties of their own behaviour. Thus, let a program be self-aware — this is the basic motivation of the so-called computational reflection, which is also considered as the reflection used in the area of programming languages [15]. In the rest of this section, we will introduce what computational reflection is (Section 2.1.1), what reflective abilities it supports (Section 2.1.2), and how Java reflection is derived from it (Section 2.1.3). 2.1.1 Computational Reflection. Reflection, as a concept for computational systems, dates from Brian Smith’s doctoral dissertation [53]. Generally, as shown in Figure 2(a), a computational system is related to a domain and it answers questions about and/or support actions in the domain [39]. As described in [39], a computational system “incorporates internal structures representing the domain. These structures include data representing entities and relations in the domain and a program describing how these data may be manipulated”. A computational system S is said to be also a reflective system, as shown in Figure 2(b), if the following two conditions are satisfied: • First, the system S has its own representation, known as its self-representation or metasystem, in its domain as a kind of data to be examined and manipulated. • Second, the system S and its representation are causally connected: a change to the representation implies a change to the system, and vice versa. The base system S should be reified into its representation before its metasystem can operate. Then the metasystem examines and manipulates its behaviour using the reified representation. If any changes are made by the metasystem, then the effects will also be reflected in the behavior of the corresponding base system. 2.1.2 Reflective Abilities. Generally, (computational) reflection is the ability of a program to examine and modify the structure and behavior of a program at runtime [23, 40]. Thus, it endows the program the capabilities of self-awareness and self-adapting. These two reflective abilities are known as introspection and intercession, respectively, and both require a reification mechanism to encode a program’s execution state as data first [15]. • Introspection: the ability of a program to observe, and consequently, reason about its own execution state. ACM Trans. Softw. Eng. Methodol., Vol. 28, No. 2, Article 7. Publication date: February 2019