Shigeru Chiba Michiaki Tatsubori. University of Tsukuba. The Java language already has the ability for reection [2, 4]. java.lang.

Similar documents
Structural Reflection by Java Bytecode Instrumentation

Program Transformation with Reflective and Aspect-Oriented Programming

Open C++ Tutorial. Shigeru Chiba Institute of Information Science and Electronics University of Tsukuba.

An Extension Mechanism. Michiaki Tatsubori. February University of Tsukuba

The Extensible Java Preprocessor Kit. and a Tiny Data-Parallel Java. Abstract

RbCl: A Reective Object-Oriented Concurrent Language. without a Run-time Kernel. Yuuji Ichisugi, Satoshi Matsuoka, Akinori Yonezawa

Jarcler: Aspect-Oriented Middleware for Distributed Software in Java

Programming Support of Design Patterns with Compile-time Reflection

Do! environment. DoT

VM instruction formats. Bytecode translator

point in worrying about performance. The goal of our work is to show that this is not true. This paper is organised as follows. In section 2 we introd

THE IMPLEMENTATION OF A DISTRIBUTED FILE SYSTEM SUPPORTING THE PARALLEL WORLD MODEL. Jun Sun, Yasushi Shinjo and Kozo Itano

Extensible Type System Framework. for a Java Pre-Processor : EPP (DRAFT) Yuuji ICHISUGI. Electrotechnical Laboratory, PRESTO JST

Macro Processing in Object-Oriented Languages

PROXY WORLD WRAPPED WORLD. link V V V. link FSV FSV DFSV. link. V: Vector FSV: FSVector DFS: DFSVector

Speeding up the Meta-level Processing of Java Through Partial. Evaluation.

CSCE 314 Programming Languages

OpenC: Extending C Programs with Computational Reflection

Generating Continuation Passing Style Code for the Co-op Language

As related works, OMG's CORBA (Common Object Request Broker Architecture)[2] has been developed for long years. CORBA was intended to realize interope

Introduction to Programming Using Java (98-388)

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Java Reflection

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming

metaxa and the Future of Reflection

Outline. Computer Science 331. Information Hiding. What This Lecture is About. Data Structures, Abstract Data Types, and Their Implementations

Language-Based Parallel Program Interaction: The Breezy Approach. Darryl I. Brown Allen D. Malony. Bernd Mohr. University of Oregon

The Art of Metaprogramming in Java. Falguni Vyas Dec 08, 2012

Profiler Instrumentation Using Metaprogramming Techniques

The Environment Model. Nate Foster Spring 2018

The Environment Model

Standard JIT Compiler - Ad-hoc construction - Limited/overspec optim - restricted portability

compute event display

CS558 Programming Languages Winter 2013 Lecture 8

Implementing Software Connectors through First-Class Methods

features of Python 1.5, including the features earlier described in [2]. Section 2.6 summarizes what is new in Python The class and the class

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming

Lecture 9 : Basics of Reflection in Java

Reflective Java and A Reflective Component-Based Transaction Architecture

Generic Function Parameter and Method Parameter Metaobjects: A Proposed Enhancement to the CLOS Metaobject Protocol. Eric L.

Introduction to Programming (Java) 2/12

Chapter 1 GETTING STARTED. SYS-ED/ Computer Education Techniques, Inc.

The Compositional C++ Language. Denition. Abstract. This document gives a concise denition of the syntax and semantics

More Relationships Between Classes

Pace University. Fundamental Concepts of CS121 1

On the Algorithm for Specializing Java Programs with Generic Types

CSc 453 Interpreters & Interpretation

Compiler Theory. (Semantic Analysis and Run-Time Environments)

CS 360 Programming Languages Interpreters

with a Meta-Level Architecture Department of Information Science, The University oftokyo In Proceedings of 7th European Conference on Object-Oriented

A taxonomy of race. D. P. Helmbold, C. E. McDowell. September 28, University of California, Santa Cruz. Santa Cruz, CA

hexpressioni ::= hvariablei j hself evaluating literali j (quote hdatumi) j (lambda (hvariablei*) hexpressioni + ) j (if hexpressioni hexpressioni hex

CS 251 Intermediate Programming Methods and Classes

CSCE 314 Programming Languages. Type System

CS 251 Intermediate Programming Methods and More

Mid-Term 2 Grades

interface MyAnno interface str( ) val( )

CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures. Dan Grossman Autumn 2018

Inheritance (Chapter 7)

A Survey of Three Approaches to the Automation of Design Patterns

JPred-P 2. Josh Choi, Michael Welch {joshchoi,

Short Notes of CS201

Week 3: Functions and Data. Working with objects. Members of an object. = n 1d 2 n 2 d 1. + n 2. = n 1d 2. = n 1n 2 / n 2. = n 2

Week 3: Functions and Data

residual residual program final result

First IS-A Relationship: Inheritance

Selected Java Topics

Design and Implementation of Parallel Java with. Global Object Space. L. V. Kale, Milind Bhandarkar, and Terry Wilmarth

CMSC131. Inheritance. Object. When we talked about Object, I mentioned that all Java classes are "built" on top of that.

CS201 - Introduction to Programming Glossary By

COP 3330 Final Exam Review

Natural Semantics [14] within the Centaur system [6], and the Typol formalism [8] which provides us with executable specications. The outcome of such

callee s frame... arg k caller s frame

2 Data Reduction Techniques The granularity of reducible information is one of the main criteria for classifying the reduction techniques. While the t

Core JAVA Training Syllabus FEE: RS. 8000/-

Zhifu Pei CSCI5448 Spring 2011 Prof. Kenneth M. Anderson

Types. Type checking. Why Do We Need Type Systems? Types and Operations. What is a type? Consensus

Assertions, pre/postconditions

New Programming Paradigms

Java Overview An introduction to the Java Programming Language

More About Objects. Zheng-Liang Lu Java Programming 255 / 282

reasonable to store in a software implementation, it is likely to be a signicant burden in a low-cost hardware implementation. We describe in this pap

CIS4/681 { Articial Intelligence 2 > (insert-sort '( )) ( ) 2 More Complicated Recursion So far everything we have dened requires

9/5/17. The Design and Implementation of Programming Languages. Compilation. Interpretation. Compilation vs. Interpretation. Hybrid Implementation

Object Model. Object Oriented Programming Spring 2015

INPUT SYSTEM MODEL ANALYSIS OUTPUT

Parametric Polymorphism for Java: A Reflective Approach

CSE413: Programming Languages and Implementation Racket structs Implementing languages with interpreters Implementing closures

Semantic Analysis. Lecture 9. February 7, 2018

Late-bound Pragmatical Class Methods

5 Distributed Objects: The Java Approach

Weiss Chapter 1 terminology (parenthesized numbers are page numbers)

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

CSE P 501 Exam 8/5/04

m() super.m (execution path) extension f n() f.m n() o.m extension e m() n() m() extensible object o composite object (o < e < f)

Implementation of Customized FindBugs Detectors

The S-Expression Design Language (SEDL) James C. Corbett. September 1, Introduction. 2 Origins of SEDL 2. 3 The Language SEDL 2.

Assignment 5. Introduction

Linguistic Reflection Via Mirrors

CS558 Programming Languages

UNIT TESTING OF C++ TEMPLATE METAPROGRAMS

Transcription:

A Yet Another java.lang.class Shigeru Chiba Michiaki Tatsubori Institute of Information Science and Electronics University of Tsukuba 1-1-1 Tennodai, Tsukuba, Ibaraki 305-8573, Japan. Phone: +81-298-53-5349 Fax: +81-298-53-5206 E-mail: chiba@is.tsukuba.ac.jp 1 Introduction The Java language already has the ability for reection [2, 4]. java.lang.class is a class for class metaobjects and provides the ability for introspection at runtime. At runtime, the Java programmers can inspect various information, for example, the class of a given object, which methods that class has, and so forth. They can also get the value of a eld and invoke a method specied by a character string. For example, they may write the following code: Person p = new Person("Joe"); Class c = p.getclass(); Field f = c.getfield("name"); // the eld name is a variable String name = (String)f.get(p); // same as String name = p.name; However, the Java language has not provided the ability for language customization, or intercession, which is another kind of reection. The Java programmers cannot change the super class of a class, alter the behavior of method invocation, or extend the syntax. A few extensions to Java, such as MetaJava [3], have been proposed to support the ability for language customization, but their abilities are limited to customizations that do not imply severe performance impacts. This paper proposes an extended version of java.lang.class, which enables more comprehensive language customization than other similar systems. To avoid performance degradation, we employ a technique called compile-time reection. Most of customizations are statically applied to a Java program at compile time and the compiled code is executed by the regular Java virtual machine (JVM) with almost no performance overheads. 1

In the rest of this paper, we rst mention requirements for the ability for language customization. Then we overview the proposed extension to Java's reection mechanism. 2 Requirements for customizability First of all, we briey summarize the kinds of language customization that we should be able to perform in Java by the extended reection mechanism. These customizations are considerably useful in practice according to our experience with OpenC++ [1]. To customize the structure of a class The reection mechanism should allow the meta-level programmers to manipulate the structure of a class. The programmers should be able to add a new method and eld to a class and remove them from a class. Also, various properties of a class, such as the super class, the name of a method, the type of a led, and the access rights to members, should be modiable. For example, the following code should be accepted: Class type = Class.forName("double"); Field f = new Field(type, "z"); Class c = Class.forName("Point"); c.addfield(f); // The double eld z is added to Point Moreover, the programmers should be able to create a new class, which is derived from other classes. This ability is useful to implement a distributed Java object. It makes it unnecessary for the programmer to explicitly dene a class for the proxy object, which is automatically derived from the class for that distributed object if that ability is provided. To alter the behavior of operations on objects The signicance of the ability to reimplement the behavior of the operations on particular objects is well known to people who are studying the use of reection in practice. Those operations include method calls, eld accesses, operator (for example, + and -) applications, type coercion (i.e. type casting). Awell-known example of the use of this ability is to reimplement method calls on a proxy object so that the method calls are dispatched to the remote object represented by that proxy object. Another, but less practical, example is to reimplement eld accesses so that a debug message is 2

printed whenever the elds are read on particular objects. Here is a pseudo code for implementing that behavior: class VerboseClass extends Class { Object fieldread(object o, Field f){ System.out.println(f.getName() + " is read."); return super.fieldread(o, f); If a eld is read on the objects the metaclass of that is VerboseClass, then the method fieldread() is called so that a debug message is printed. To alter variable types Another kind of language customization is to change the interpretation of variable types. For example, the meta-level programmers may want to store a proxy object in a variable the type of that is a distributed object. Or, they may want to do so if the variable is declared with a specic modier such as remote. The meta-level program to implement that customization would be something like this: class DistributedClass extends Class { Class realvariabletype(string modifier){ if (modifier.equals("remote")) return Class.forName("Proxy" + this.getname()); else return this; If this metaclass DistributedClass is associated with a class Person, then avariable of the Person class: remote Person joe; is interpreted as a variable of the ProxyPerson class. This kind of language customization is also useful to implement a mechanism similar to C++'s template. It would be convenient if the base-level programmers can write: Vector of String v; and then the variable v is interpreted as the variable of the class VectorOfString, which is automatically derived by the metaclass from the class Vector. 3

To dene a new kind of syntax The last is the ability for syntax extensions. For example, to utilize parallel computers, the programmers may want to dene a new control structure forall, which is used as follows: Matrix m1, m2; : m1.forall(int i, int j, double e){ e = m2.elementat(i, j) * 2.0; The block fg is executed on each element of the matrix m1. In the block, e is bound to that element, and i and j are bound to the indexes. This control structure should be compiled into byte code using threads to execute the block in parallel. A much simpler example is an unless statement. It is the opposite of an if statement: unless (b > 0) { b = -b; If the expression b > 0 is false, then the block f b = -b; g is executed. At the meta level, the unless statement should be interpreted by a method like the following: void unlessstatement(environment env, Expression exp, Block blk){ if (!exp.evaluate(env)) blk.evaluate(env); This method is invoked if the program execution reaches an unless statement. It interprets the program according to the semantics of the unless statement. 3 Use of compile-time reection If we modify the regular Java virtual machine (JVM), the ability for the language customizations shown in the previous section could be easily implemented. However, this implementation may make it dicult to apply optimization techniques on method dispatch and eld access to the JVM 4

since methods and elds may be dynamically altered, removed, and added. In general, those optimization techniques improve execution performance assuming that all the methods and elds are statically given. Modifying the JVM for implementing the ability for language customizations is naive but may make the JVM inecient especially if it includes a just-in-time (JIT) compiler or other complex optimizers. To give the ability for language customization to Java, we do not modify the JVM but modify the Java compiler with a technique called compiletime reection. With this technique, most of the customizations are applied at compile time and the compiled Java program is executed by the regular JVM. This means that runtime overheads due to the language customization are signicantly limited. Although compile-time reection has been already employed by other systems such as OpenC++ [1], this paper discusses the application of compile-time reection to the metaobjects providing the ability for introspection at runtime. The metaobjects of the previous systems work only at compile time but they do not provide any ability for reection at runtime. 3.1 openjava.mop.ojclass We are currently implementing a class openjava.mop.ojclass for class metaobjects and the associate classes such as OJMethod. These classes are reimplementations of java.lang.class and Method although their names begin with OJ for easy distinction, and they provide the ability for not only introspection but also language customization. The ability for language customization is implemented with compile-time reection in cooperation with our Java compiler, called the OpenJava compiler. Our OJClass supplies all the methods that Java's Class does. In addition, OJClass supplies a method transformclass(), which is an empty method but overridable by a subclass. The meta-level programmers who want to customize the structure of a class can dene a subclass of OJClass and override this method. Since transformclass() is called on every baselevel class associated with that subclass, the programmers can customize the structure of that base-level class in that method, for example, they can add a new eld: void transformclass(environment e){ Class type = Class.forName("double"); OJField f = new OJField(type, "z"); addfield(f); // add this eld z to the base-level class 5

The method addfield() is supplied by OJClass. It adds a given eld represented by aojfield object to the class. A unique feature is that our Java compiler internally creates a class metaobject for every base-level class in the processed source program. If the programmer associates a subclass of OJClass with a base-level class, then the compiler instantiates that subclass for that base-level class at compile time. Then the compiler calls transformclass() on all the class metaobjects and translates the source program according to the results of that method. In the case of the example above, the result of addfield() is reected on the source program so that the denition of that base-level class is modied to include the added eld z. After the source-level translation, the program is compiled by the regular Java compiler. Since the resulting byte code includes a class that the customization of the class structure has been already applied to, it does not imply any runtime overheads due to the reection. 3.2 The behavior of operations on objects Reecting changes of the structure of a class on the source program at compile time is easy and straightforward but how should we deal with changes of the behavior of operations on objects, such as a method call? In the previous section, we showed an example of meta-level methods representing new behavior of the operations. The method fieldread() in that example is apparently meaningless if it is execute at compile time; it must be executed at runtime. To solve this problem, our OpenJava compiler translates an expression executing an operation on an object so that the class metaobject intercepts that operation. Suppose that you want to alter the behavior of eld accesses on Person objects. To do this, you dene a subclass of OJClass to override fieldread(), and associate that subclass to the class Person. If a variable p is a Person object, then this expression: p.name is translated by the OpenJava compiler into this: (String)(OJClass.getClass(p).notifyRead(p, "name")) At runtime, this expression calls notifyread() on the class metaobject for p. Note that the class metaobject exists at both compile-time and runtime. The implementation of notifyread() is supplied by OJClass: Object notifyread(object o, String field_name){ OJField f = getfield(field_name); return readfield(o, f); 6

This method looks up the eld metaobject and calls readfield() with it, which implements the new behavior of the base-level method call. The other operations such as method calls are also processed in the same technique. All the expressions including operations on objects are translated at compile time so that the class metaobjects can intercept the operations at runtime. This technique enables changes of the behavior of those operations without modifying the JVM. 3.3 Variable types The OpenJava compiler also applies changes of the interpretation of variable types to the source program at compile time. The implementation is simple the compiler replaces the type name of the declaration of the variable with the type returned by the class metaobject. Recall the example in the previous section. The method realtypevariable() returned the class metaobject for the type of a given variable according to the modier. 3.4 Syntax extensions Finally, we mention how the OpenJava compiler deals with syntax extensions. The technique used for changing the behavior of operations on objects cannot be eective for syntax extensions because it requires closures. In the example of an unless statement in the previous section, the method unlessstatement() took two arguments, exp and blk, and interpreted the statement with them. These arguments are closures and calling evaluate() on these closures must return the resulting value of executing the code. The closures cannot be implemented with a simple program translation in Java. We enable syntax extensions in Java with a dierent technique. We use macro expansion like Lisp's to implement syntax extensions. For example, the unless statement: unless (b > 0) { b = -b; is expanded by a class metaobject into a regular Java statement: if (!(b > 0)) { b = -b; To specify the macro expansion, our openjava.mop.ojclass supplies an overridable method expandnewstatement(). This is called by the OpenJava 7

compiler at compile time to perform the macro expansion. To expand an unless statement, the meta-level programmers can override expandnewstatement() as follows: ParseTree expandnewstatement(environment e, ParseTree statement) throws SyntaxError { if (statement.first().equals("unless")) { ParseTree expr = statement.second(); ParseTree block = statement.third(); return new ParseTree("if(!" + expr.tostring() + ")" + block.tostring()); else throw new SyntaxError(); This method takes a compile-time environment and a parse tree representing the unless statement. The parse tree is a linked list similar to Lisp's list data structure. The method expandnewstatement() transforms the given parse tree and returns a dierent parse tree representing regular Java code. The OpenJava compiler substitutes the resulting parse tree for the original unless statement in the source program. Unfortunately, this implementation requires changing the protocol of the class metaobjects. The meta-level programmers cannot dene the semantics of the unless statement in the interpretation style shown in the previous section. Instead, they have to dene it in the macro-expansion style. The drawbacks of this change is controversial; some say they are serious but we do not think so. According to our experiences with OpenC++, dening a new syntax in the macro-expansion style is not dicult but rather it is often intuitive. 4 Concluding remarks We are implementing a reection mechanism for Java, which replaces Java's original java.lang.class. Our reection mechanism provides the ability for language customization that is more comprehensive than Java's original one and similar extensions [3]. To avoid performance drawbacks, we employ a technique called compiletime reection. Our reection mechanism is implemented by a pair of our OpenJava compiler and a class library substituting java.lang.class and java.lang.reflect.*. The Java virtual machine (JVM) is not modied 8

at all. The OpenJava compiler applies language customizations written in meta-level programs to the base-level programs at compile time so that extra costs due to reection are not necessary at runtime. On the other hand, our approach implies limitations on the ability for customization. For example, the meta-level programmers cannot change the structure of a class dynamically at runtime. We think that addressing this problem needs to modify the JVM and involves too much overheads to justify its benets for the time being. This issue is our future work. References [1] Chiba, S., \A Metaobject Protocol for C++," in Proc. of ACM Conf. on Object-Oriented Programming Systems, Languages, and Applications, no. 10 in SIGPLAN Notices vol. 30, pp. 285{299, ACM, 1995. [2] Java Soft, Java TM Core Reection API and Specication. Sun Microsystems, Inc., 1997. [3] Kleinoder, J. and M. Golm, \MetaJava: An Ecient Run-Time Meta Architecture for Java," in Proc. of the International Workshop on Object Orientation in Operating Systems (IWOOS'96), IEEE, 1996. [4] Kramer, D., JDK 1.1.6 Documentation. Sun Microsystems, Inc., 1998. 9