multiple code inheritance in java - pdfs.semanticscholar.org · 1. the first implementation of...

26
Cutumisu - 1 Multiple Code Inheritance in Java Maria Cutumisu 1 , Paul Lu 1 , and Duane Szafron 1 1 Department of Computing Science, University of Alberta, Edmonton, AB, Canada, T6G 2E8 {meric, paullu, duane}@cs.ualberta.ca Abstract. Java has multiple-inheritance of interfaces, but only single- inheritance of code. This situation results in duplicated code in Java library classes and application code. This paper describes a generalization to the Java Virtual Machine (JVM) to support multiple-inheritance of code. Our approach places code in interfaces. This extension can be implemented by adding a small amount of code to a few locations in a JVM. Furthermore, a set of simple scripts allows a programmer to use multiple code inheritance with existing javac compilers. Word Count = 9,273 1 Introduction Three distinct kinds of inheritance are useful in object-oriented programs: interface inheritance, code inheritance and data inheritance. In fact, it is quite useful to design and implement software in a way that explicitly differentiates between these concepts. The motivation for separate language mechanisms is described in [1] and our long- term goal is to provide these mechanisms. Our short-term strategy is to explicitly model the three separate concepts in existing popular programming languages to evaluate the utility of concept separation, and to increase demand for separation in future languages. We show a novel way to implement multiple code inheritance in Java. This is an important step towards our goal of modeling each of these three concepts separately in Java. We begin with an informal description of the three kinds of types and their associated inheritance. The terms type and class are commonly used by researchers and practitioners to refer to six different notions: 1. a real-world concept (concept) 2. a programmatic interface (interface) 3. an implementation of a programmatic interface (implementation) 4. an internal machine representation (representation) 5. a factory for creation of instances (factory) 6. a maintainer of the set of all instances (extent) Unfortunately, most object-oriented programming languages do not separate these notions. Each object-oriented language uses various combinations of the last five notions into different language constructs to produce code that models the first concept. Java uses interface for interface. However, it combines the notions of implementation, representation and factory into a class construct. Smalltalk and C++ have less separation. They use the class construct for interface , implementation, representation and factory . Although Smalltalk provides a message that can be sent to a class object to recover all of its instances (extent), most general purpose object-oriented languages do not explicitly support the extent notion.

Upload: others

Post on 06-Nov-2019

17 views

Category:

Documents


0 download

TRANSCRIPT

Cutumisu - 1

Multiple Code Inheritance in JavaMaria Cutumisu1, Paul Lu1, and Duane Szafron1

1 Department of Computing Science, University of Alberta, Edmonton, AB,Canada, T6G 2E8

{meric, paullu, duane}@cs.ualberta.ca

Abstract. Java has multiple-inheritance of interfaces, but only single-inheritance of code. This situation results in duplicated code in Java libraryclasses and application code. This paper describes a generalization to the JavaVirtual Machine (JVM) to support multiple-inheritance of code. Our approachplaces code in interfaces. This extension can be implemented by adding a smallamount of code to a few locations in a JVM. Furthermore, a set of simplescripts allows a programmer to use multiple code inheritance with existingjavac compilers. Word Count = 9,273

1 IntroductionThree distinct kinds of inheritance are useful in object-oriented programs: interfaceinheritance, code inheritance and data inheritance. In fact, it is quite useful to designand implement software in a way that explicitly differentiates between these concepts.The motivation for separate language mechanisms is described in [1] and our long-term goal is to provide these mechanisms. Our short-term strategy is to explicitlymodel the three separate concepts in existing popular programming languages toevaluate the utility of concept separation, and to increase demand for separation infuture languages.

We show a novel way to implement multiple code inheritance in Java. This is animportant step towards our goal of modeling each of these three concepts separatelyin Java. We begin with an informal description of the three kinds of types and theirassociated inheritance.

The terms type and class are commonly used by researchers and practitioners torefer to six different notions:

1. a real-world concept (concept)2. a programmatic interface (interface)3. an implementation of a programmatic interface (implementation)4. an internal machine representation (representation)5. a factory for creation of instances (factory)6. a maintainer of the set of all instances (extent)

Unfortunately, most object-oriented programming languages do not separate thesenotions. Each object-oriented language uses various combinations of the last fivenotions into different language constructs to produce code that models the firstconcept. Java uses interface for interface. However, it combines the notions ofimplementation, representation and factory into a class construct. Smalltalk andC++ have less separation. They use the c lass construct for in ter face ,implementation, representation and factory. Although Smalltalk provides amessage that can be sent to a class object to recover all of its instances (extent), mostgeneral purpose object-oriented languages do not explicitly support the extent notion.

Cutumisu - 2

However, database languages like GemStone[2], O2[3]and Iris[4] provide amechanism for recording the instances, but combine extent with other notions usingthe language constructs class or type. In this paper we will focus on general purposeobject-oriented programming languages, so we not discuss the extent notion. Wecombine concept with interface, to enforce encapsulation. We also combinerepresentation and factory, since instances cannot be created without knowing therepresentation. Therefore, we introduce the following definitions:

1. An interface-type defines the legal operations for a group of objects(interface) that model a concept.

2. A code-type associates code with each operation of the interface-type that itimplements (implementation).

3. A data-type defines the state layout of the objects for the interface-type thatit implements (representation), provides accessor methods for this data andprovides a mechanism for object creation (factory).

4. We use the generic term, type to refer to an interface-type, a code-type or adata-type.

Inheritance is a mechanism that allows properties (interface, implementation orrepresentation) defined in a type to be used in a set of child types called its directsub-types. However, by transitivity, these properties are also inherited by all sub-types. If type B is a sub-type of type A, then A is called a super-type of type B. If alanguage restricts the number of direct super-types of any type to be one or less, thelanguage is said to have single inheritance. If a type can have more than one directsuper-type, the language supports multiple inheritance.

Interface inheritance allows a sub-type to inherit the interface (operations) of itssuper-types. The principle of substitutability says that if a language expressioncontains a reference to an object whose static type is A, then an object whose type isA or any sub-type can be used. Interface inheritance relies only on substitutability anddoes not imply code or data inheritance.

Code inheritance allows a type to re-use the implementation (binding betweenan operation and the associated code) from its parent types. Code inheritance can beused independently of data representation, since many operations can be implementedby calling more basic operations, without specifying a representation until the sub-types are defined. Java and Smalltalk only have single code inheritance, but C++ hasmultiple-code inheritance.

Data inheritance allows a type to re-use the representation (object layout) of itsparent types. This inheritance is the least useful and causes considerable confusion ifmultiple data inheritance is allowed. Neither Java nor Smalltalk support multiple datainheritance, but C++ does.

Although we have used the term sub-typing to refer to interface, implementationand representation inheritance, the terms subtyping and subclassing are often used todescribe these inheritance relationships in programming languages ([5][6]). Subtypingusually refers to the relationship between the interfaces (interface), while subclassingusually refers to the relationship between combined implementation/representation.Table 1 shows the separation and inheritance characteristics of several languages:Java, C++, Smalltalk, Cecil [7] and its ancestor BeCecil [8], Emerald [9], Sather [10],Lagoona [11] and Theta [12]. This list is not intended to be complete. A more generaland extensive review of type systems for object-oriented languages has been

Cutumisu - 3

compiled[13]. Although there is growing support for separation of interface, theconcepts of implementation and representation are rarely separated at present. Wehope to change this.

Table 1. Concept separation constructs and single/multiple inheritance in some existinglanguages

Language interface implementation representationJava multiple / interface single / class single / classC++ multiple / class multiple / class multiple / classSmalltalk single / class single / class single / classCecil/BeCecil multiple / type multiple / object multiple / objectEmerald implicit multiple /

abstract typenone / objectconstructor

none / objectconstructor

Sather multiple / abstractclass

multiple /class multiple / class

Lagoona multiple / category none / methods single / typeTheta multiple / type single / class single / class

The research contributions of this paper are:1. The first implementation of multiple code inheritance in Java. It is based on

the novel concept of adding code to a new type of interface called a code-type. A super call mechanism that resembles the one in C++ is alsointroduced.

2. All existing programs continue to work and suffer no performance penalties.Only localized modifications are made to the JVM and no changes are madeto the sytax of Java or to the compiler to support these changes. However,syntax changes that would simplify coding are proposed.

3. We show how multiple code inheritance reduces the amount of identical andsimilar code (e.g. the standard libraries) to simplify program constructionand maintenance.

2 Using Multiple Code Inheritance in JavaIn this Section we motivate the use of multiple code inheritance using some

classes from the java.io library. Java currently supports multiple interfaceinheritance. Consider the Java class RandomAccessFile (from java.io) thatimplements the interfaces DataInput and DataOutput, as shown in Fig. 1. Formodeling, we have the nice situation where every instance of RandomAccessFilecan be considered as both a DataInput and a DataOutput. This providessubstitutability so that any reference that is declared as a DataInput orDataOutput can be bound to a RandomAccessFile.

Java does not support multiple code inheritance and this causes implementationand maintenance problems. One common example is that identical code appears inseveral classes. This makes programs larger and harder to understand. In addition,code can be copied incorrectly and changes not propagated to all copies. Fig. 1 showsone example from the Java library classes. Much of the code that is inRandomAccessFile is identical or similar to the code in DataInputStream

Cutumisu - 4

and DataOutputStream. Although it is possible to re-factor this hierarchy tomake RandomAccessFile a subclass of either DataInputStream orDataOutputStream, it is not possible to make it a subclass of both, since Javadoes not support multiple class inheritance.

Fig. 1. A class can inherit from multiple interfaces in Java, where the class supplies bothimplementation and representation

The method writeFloat(float)is an example of copied code that appearsin both DataOutputStream and RandomAccessFile:

public final void writeFloat(float v) throws IOException {writeInt(Float.floatToIntBits(v));

}

There is one other method that is identical in both DataOutputStream andRandomAccessFile and there are also eight methods that have identical code inboth DataInputStream and RandomAccessFile.

Now that these common methods have been found, how can code inheritance beused to share them? Fig. 1 shows that we need a common ancestor ofDataInputStream and RandomAccessFile to store the eight common readmethods and a common ancestor class of DataOutputStream andRandomAccessFile to store the common two write methods. Since we are sharingcode, this ancestor cannot be an interface. It also cannot be a class since we needmultiple inheritance and Java doesn't support it. In fact, it should be a multipleinheritance code-type. Fig. 2 shows the common code factored into two code-types:InputCode and OutputCode. In this approach, a code-type implements the codefor one or more interfaces and a class implements the data-type and accessor methodsfor a single code-type.

The benefit of this approach may seem questionable to save only ten duplicatemethods. However, it is not only exact duplicate methods that can promoted higher inthe hierarchy. There are many situations in the java libraries where multiple codeinheritance can be used to promote non-identical methods, if they are abstractedslightly.

DataInputStream DataOutputStream

DataInput DataOutput

RandomAccessFile

interface classimplementation / representation

Legend

Cutumisu - 5

Fig. 2. Adding multiple-inheritance code-types to Java

As an example, consider the methods for readByte() that appear in classesDataInputStream and RandomAccessFile, and only differ by a single line ofcode:

public final byte readByte() throws IOException { int ch = this.in.read(); // int ch = this.read(); in RAF if (ch < 0) throw new EOFException(); return (byte)(ch);}

The code before the comment (// ) on the second line appears in classDataInputStream . The code after the comment appears in classRandomAccessFile. These methods can be replaced by a single common methodthat can be promoted to the code-type, InputCode. To do this, we replace thesecond line by:

int ch = this.source().read();

where source() is a new method that returns this.in for DataInputStreamand returns this for RandomAccessFile. The common method is now promotedto InputCode. This exact abstraction can be used to share three other similarmethods in the same two classes.

However, this abstraction can also be generalized to move a number of similarmethods from DataOutputStream and RandomAccessFile to the commoncode-type, O u t p u t C o d e . As an example, consider the method forwriteChar(int) that appear in classes DataOutputStream andRandomAccessFile:

public final void writeChar(int v) throws IOException {OutputStream out = this.out; // out = this; in RAF

InputCode OutputCode

DataInput DataOutput

DataInputStream RandomAccessFile DataOutputStream

interface class code-type implementation representation

Legend

Cutumisu - 6

out.write((v >>> 8) & 0xFF);out.write((v >>> 0) & 0xFF);incCount(2); // this line missing in RandomAccessFile

}

The code before the comment (// ) on the second line appears in classDataOutputStream . The code after the comment appears in classRandomAccessFile. To replace these methods by a common method, we start byreplacing the second line by an abstracted line analogous to the previous example.However, in this case, the code before the comment (//) on the fifth line appears inclass DataOutputStream, but does not appear in class RandomAccessFile. Ina situation like this, we can abstract all of the lines except for the last one into acommon method and move it up to the code-type OutputCode:

public final void writeChar(int v) throws IOException {Sink out = this.sink();out.write((v >>> 8) & 0xFF);out.write((v >>> 0) & 0xFF);

}

The method s i n k ( ) is a new method that returns t h i s . o u t forDataOutputStream and returns this for RandomAccessFile. No methodfor writeChar(int) needs to appear in RandomAccessFile, since thiscommon inherited method suffices. However, in DataOuputStream we need toaccount for the missing last line using a classic refinement method:

public final void writeChar(int v) throws IOException {super(OutputCode).writeChar(v);incCount(2);

}

Notice that super(OutputCode) is not standard Java! This call is requesting acall to a supercode-type (OutputCode) instead of a superclass. In general, sincethere may be multiple immediate supercode-types, the supercall must be qualified bythe supercode-type that is wanted. This is one of the standard approaches to solvingthe super ambiguity problem of multiple inheritance and it will be discussed later inthis paper, along with a technique we use to avoid the need for a special compiler toimplement qualified supercalls.

Table 2 and Table 3 show the number of methods and lines of executable codethat could be promoted in these stream classes of the java.io libraries, if Javasupported multiple code inheritance. For the lines, we only counted executable linesand declarations, not comments or method signatures. However, more important thanthe size of the reductions is the reduced cost of understanding and maintaining theabstracted code. Note that even though most of the method bodies of six methodsmove up from DataOutputStream to OutputCode, small methods remain thatmake super calls to these promoted methods. That is why the method decrease issmaller for DataOutputStream, than its code decrease.

Cutumisu - 7

Table 2. Method promotion in the Java stream classes using multiple code inheritance.

Class identicalmethods

usingabstract

abstractplus super

totalpromoted

methoddecrease

DataInputStream 8/19 4/19 0/19 12/19 63%DataOutputStream 2/17 0/17 0/17 2/17 12%RandomAccessFile 10/45 4/45 6/45 20/45 44%

Table 3. Code promotion in the Java stream classes using multiple code inheritance.

Class initial lines added linesabstractionand super

net linesabstractionand super

linedecrease

DataInputStream 127 1 84 34%DataOutputStream 83 7 66 20%RandomAccessFile 154 2 97 37%

Note that this abstraction requires the creation of two new interfaces, Sourceand Sink and that each contains one abstract method, source() and sink()respectively. It also requires one line method implementations inDataInputStream (return this.in) and DataOutputStream(return this.out) respectively. Both of these methods are also implemented inRandomAccessFile with the code: return this. The resulting inheritancehierarchy for the Stream classes is shown in Fig. 3

Fig. 3. The revised Stream hierarchy to support multiple code inheritance.

InputCode OutputCode

DataInput DataOutput

DataInputStream RandomAccessFile DataOutputStream

interfac class code-type implementation representation

Legend

InputStream OutputStream

Source Sink

Cutumisu - 8

The Source and Sink interfaces were created, since they represent the leastcommon supertypes of the types returned by the source() and sink() methods.Notice that since the abstract methods declared in the new Source and Sinkinterfaces can be implemented using only accessor methods, there is no need toinclude code-types between the interfaces and the classes (DataInputStream,DataOutputStream and RandomAccessFile) that implement them.

3 Code-Types in JavaSince there is no concept of a code-type in Java, we must either add a language

construct, or use either an interface or a class to represent a code-type. At first glance,an abstract class seems to be the obvious choice for a code-type. However, ourexamples in the previous Section clearly indicate the utility of multiple inheritance forcode-types. If code-types were represented by classes (abstract or concrete), wewould need to modify Java to support multiple inheritance of classes. Besides beingdifficult, this would have the undesirable side-effect of providing multiple datainheritance, since classes are also used for representation. On the other hand, if weuse interfaces to represent code-types, we can use Java's current multiple-inheritanceof interfaces.

One of the problems with using interfaces for code-types is that we would needto modify the JVM and compiler to support code in interfaces. We have solved theproblem of supporting code in interfaces by making localized changes to the JavaVirtual Machine (JVM). We have solved the compiler problems by introducingscripts that work with a standard Java compiler. An alternate approach is to use innerclasses [14]. However, this approach differentiates between using code fromsuperclasses and superinterfaces, by using inheritance along the superclass chain anddelegation along the interface chains. Our approach accesses code in superinterfacesand superclasses using the same inheritance mechanism as the current JVM.

We are not advocating the abolition of interfaces as pure interface-types! We aresuggesting that we can use some interfaces to represent code-types and otherinterfaces to represent interface-types. Ultimately we would like to see a Javalanguage extension that uses different keywords for these different languageconstructs (a code-type could be called an implementation). However, in themeantime, programmers can use separate interfaces to represent interface-types andcode-types and gain multiple code inheritance.

We do not support multiple data inheritance, since data cannot be declared ininterfaces. However, multiple data inheritance causes many complications in C++.For example, if multiple-inheritance is used in C++, an offset for the this pointermust be computed at dispatch time [15]. This is not necessary for multiple codeinheritance. At first glance, it may appear that the opportunities for multiple codeinheritance without multiple data inheritance are few. However, examples like the onein this Section are abundant in the standard Java libraries and many applicationprograms.

4 Method Dispatch in the Unmodified JVMTo implement multiple code inheritance, we modified SUN's JVM 1.2.2 to executecode in interfaces (www.sun.com/software/communitysource/java2/ download.html).

Cutumisu - 9

We know of no elegant way to implement multiple code-inheritance in Java withoutmodifying the JVM. Although the approach of using inner classes [14] is interesting,its use of delegation inheritance along the interface chains is not very appealing fromthe language consistency perspective. It makes interface inheritance second class. Wehave previous success modifying JVM dispatch to support multi-methods [16]. Ourchanges to support multiple code inheritance are concise and localized and shouldtransfer to other JVMs. To understand the changes that we made to the JVM, it isnecessary to first understand how an unmodified JVM performs dispatch.

In this Section we describe how a call-site like input.readByte() isdispatched in the unmodified virtual machine. At compile-time, this call-site istranslated to a JVM instruction whose op-code depends on the static type of input.If the static type is a class, then the generated op-code is invokevirtual. If the statictype is an interface, then the op-code is invokeinterface. In either case, a methodreference is also stored as an instruction operand – an index into the constant pool. Amethod reference contains the static type of input (a class or an interface) and themethod signature of readByte().

At run-time, the compiled code for each method is stored in a method-block thatcontains complete information for the method, including its signature and a pointer toits byte-codes. In the case of interfaces, the code pointer is currently null, but wechange this as described in Section 5.1. Method dispatch is a two-step process. In thefirst step, called resolution, a resolved method-block is found whose signaturematches the call-site. The resolved method-block will not necessarily be executed.However, it will have the correct signature and will contain enough information toquickly find the execution method-block that is executed in the second step.

4.1 Method Tables and Virtual Method Tables

In Sun's JVM, a method table (MT) is an array of method-blocks that are declared(not inherited) in a class or interface. Fig. 4 shows the MTs for some classes andinterfaces from the java.io package, but many methods have been excluded forsimplicity.

Each of the classes has one method-block in its MT for each declared method inthe class. For example, DataInputStream has a method-block forread(byte[]) since it overrides this method, but has no method-block forclose() since this method is not overriden. The interface, DataInput, hasmethod-blocks for its methods, readFloat() and readInt(), even though theycontain no code.

To resolve an invokevirtual instruction, the JVM uses the method reference toobtain the static class and a method signature. It then searches the MT of this class fora method-block whose signature matches. If no match is found, it searches the MTsalong the superclass chain. The compiler guarantees that a match will be found.However, it is possible that the resolution method-block is not the correct executionmethod-block.

Cutumisu - 10

Fig. 4 The MT, VMT and IMT for some classes and interfaces in the java.io package.

interface: DataInput

MTreadFloat();readInt();

01

Declared Methods:readFloat();readInt();

interface: DataOutput

MTwriteInt(int); 0

Declared Methods:writeInt(int);

Class: DataInputStream

0 -

. . .1 clone()

11 wait()

13 read(byte[])

VMT

12 close()

Declared Methods:DataInputStream(InputStream) {...}read(byte[]) {...}readFloat() {...}readInt() {...}

MT

read(byte[])readFloat()

1314

init(InputStream) 0

readInt() 15

14 readFloat()15 readInt()

IMTDataInput 14 15

Class: FilterInputStream

0 -

. . .1 clone()

11 wait()

13 read(byte[])

VMT

12 close()

Declared Methods:FilterInputStream(InputStream)close();read(byte[]);

MT

close()read(byte[])

1213

init(InputStream) 0

Class: RandomAccessFile

0 -

. . .1 clone()

11 wait()

13 readInt()

VMT

12 readFloat()

Declared Methods:RandomAccessFile(String, String)readFloat() {...}readInt() {...}writeInt() {...}

MT

readFloat()readInt()

1213

init(InputStream) 0

writeInt() 14

14 writeInt()

IMTDataInput 12DataOutput 14

13

DataInputIMT

DataOutputIMT

interface

class

implementation

methoddefinitions

pointer

subclass

Legend

Cutumisu - 11

For example, consider the classes of Fig. 4, a variable declaration,FilterInputStream input, and a call-site input.read(aByteArray),where input is bound to an instance of DataInputStream. Resolution producesthe resolution method-block for read(byte[]) in class FilterInputStream.However, the execution method-block should be read(byte[]) inDataInputStream. If the index of a method-block in its MT was invariant alongthe superclass chain, the resolved method-block, read(byte[]) inFilterInputStream could store this invariant index and it could be used as anindex into the MT of the dynamic class of the receiver object (DataInputStreamin this example). Unfortunately, MT indexes are not invariant. For example,read(byte[]) has index 2 in the MT of FilterInputStream and index 1 inthe MT of DataInputStream, as shown in Fig. 4

Therefore, another data structure, called a virtual method table (VMT), is used tostore invariant indexes for all methods along a superclass chain. Each VMT entryholds a reference to a method-block that has been declared or inherited. When a childclass overwrites a VMT entry to point to a method-block in a different MT, themethod-block's VMT index does not vary. When a VMT is constructed, it first copiesits superclasses' VMT and then extends it. For example, the indexes of all methodsinherited from Object are the same in all VMTs and the index (13) ofr e a d ( b y t e [ ] ) is the same in F i l t e r I n p u t S t r e a m andDataInputStream.

The invariance of VMT indexes is essential for fast dispatch when substitutabilityis required. The MT and VMT are constructed when a class is loaded. Afterresolution, the execution method-block for an invokevirtual instruction is computedfrom the resolution method-block, using Formula 1.

executeMB = receiver.dynamicClass.VMT[resolvedMB.vmtIndex] (1)

Resolution is slow since it searches MTs. Therefore, byte-code quicking modifies thebyte-codes at each invokevirtual call-site to contain a reference to the resolvedmethod-block instead of the original symbolic method reference.

A VMT is similar to a virtual function table of C++. In C++, the compiler insertsa virtual function table index at each virtual function call-site. In Java, the compilerinserts a symbolic method reference and the first call-site execution resolves thissymbolic reference and modifies the byte-codes so that future executions use a VMTindex.

Unfortunately, this dispatch mechanism does not work for interfaces, due tomultiple-inheritance. Fig. 4 illustrates the problem. The method readInt(),declared in the interface DataInput that is implemented by classesDataInputStream and RandomAccessFile, can have different indexes (15and 13) in the VMTs. Each class may inherit methods from different superclasses orimplement different interfaces. Therefore we need another data structure, to facilitateinterface method dispatch (i.e. invokeinterface).

Cutumisu - 12

4.2 Interface Method tables

If a method receiver is an expression with a static interface type, the call-site willcontain an invokeinterface bytecode, instead of an invokevirtual. Resolution of aninvokeinterface is similar to resolution for an invokevirtual, except that the methodreference includes an interface instead of a class. Resolution starts at the interfacemethod table (IMT) of this interface. An IMT has one entry for each interface that isextended or implemented (directly or indirectly) by its class or interface. Duringresolution, the JVM starts with the zeroth entry of the interface's IMT, which is theinterface itself. The MT of this interface is searched for a matching method. If one isnot found, the MTs of subsequent interfaces in the IMT are searched. The compilerguarantees that a signature match will be found.

Unfortunately, the resolved method-block may not be the execution method-block. In the invokevirtual case, the resolved method-block contained an invariantindex into the VMT of the receiver object's dynamic class. In the invokeinterfacecase, the resolution method-block contains a local MT offset. To complete thedispatch, an index must also be computed. The index is for the IMT of the dynamicreceiver's class, where the interface of the resolved method-block is located. The JVMfirst searches the IMT of the receiver's dynamic class for a match to the interface ofthe resolved method-block. The location of the match is an index, called a guess (forreasons that will be explained later). The IMT entry indexed by guess contains anarray of VMT indexes. The offset in the resolved method-block is used as an offsetinto this array to obtain the correct VMT index. Formula 2 shows how to compute theexecution method-block of an invokeinterface from the resolved method-block andthe guess.

itable = receiver.dynamicClass.IMT[guess];vmtIndex = itable.vmtIndexArray[resolvedMb.mtoffset];executeMB = receiver.dynamicClass.VMT[vmtIndex] (2)

For example, consider a variable, input, that is declared to be a DataInput,and a call-site: input.readInt(). The resolved method-block is readInt()in DataInput. The resolved method-block has interface DataInput and methodtable offset 1. First, assume that the receiver object's dynamic class isRandomAccessFile. A search through the IMT of RandomAccessFile for theinterface DataInput produces a guess of 0. Offset 1 of entry 0 of this IMT is 13and the VMT entry at index 13 is the code for readInt(). Alternately, if thereceiver object is an instance of DataInputStream then a search through the IMTof DataInputStream for the interface DataInput also produces a guess of 0. Inthis case, offset 1 of entry 0 of its IMT is 15 and the VMT entry at index 15 is theright code for readInt(). Although the VMT index is not constant across classes(e.g. 13, then 15), the IMT index, together with the array offset, can be used to findthe correct code. The IMT provides an extra level of indirection that solves theproblem of inconsistent indexing of interface methods between classes. This extralevel of indirection is analogous to the way C++ implements multiple-inheritanceusing multiple virtual function tables.

Byte-code quicking modifies the byte-codes at each invokeinterface call-site. Theguess is stored in the quicked bytecodes, in addition to a reference to the resolved

Cutumisu - 13

method-block, so the search does not normally need to be re-done. However, it ispossible that the guess at a call-site could be incorrect.

To see how the guess can be wrong, consider Fig. 4, except assume that the IMTin class RandomAccessFile has the DataInput and DataOutput entries inthe reverse order. This can happen since classes can implement multiple interfaces, sothat the order of interfaces across different IMTs can be different. Re-consider the twosuccessive executions of the call-site, input.readInt() described previously. Inthis case, the first call-site execution (with dynamic class RandomAccessFile)will generate a guess of 1 and an offset of 1. However, when the second execution ofthis call-site uses the guess of 1, it would be out of bounds in the IMT ofDataInputStream. To solve this problem, the interface at the IMT entry withindex guess is always compared to the interface of the resolved method-block that isstored in the quicked byte-codes and, if they are different, a new search of the IMT isconducted and the new guess is cached in the quicked byte-codes. This approach isanalogous to the inline-caching method-dispatch technique [17] and can suffer fromthe same thrashing problems. Nevertheless, it is still faster than doing a full resolutionfrom a symbolic method signature for each execution of the call-site.

To support code in interfaces, we modify the JVM class loader code thatconstructs the IMT. To understand our modifications, it is necessary to understand thealgorithm that the class loader currently uses to construct the IMT:

Algorithm ConstructIMT(class)1. class.imt = new IMT();2. copy entries from class.superclass.imt to class.imt;3. for each direct interface in class4. copy unique entries of interface.imt to class.imt;5. end for6. for each imtIndex in class.imt7. interface = class.imt[imtIndex].interface;8. for each mtIndex in interface.MT9. imb = interface.MT[mtIndex];10. signature = imb.signature();11. vmtIndex = class.vmt.findSignature(signature);12. class.imt[imtIndex].array[mtIndex] = vmtIndex;13. // line reserved for JVM modifications later14. end for15. end forend ConstructIMT algorithm;

The class loader creates a new IMT for the class being loaded and then copies theIMT entries of the superclass. The class loader then loops over each interface that isexplicitly implemented by the class. All of the IMT entries that are not in the newIMT are copied, but each interface is only copied once. After the class loader is donelooping through all implemented interfaces and the IMT has all of its entries, the classloader loops through each slot in the IMT (line 6), to fill in the index arrays. For eachslot, the interface pointer is de-referenced to obtain the interface (line 7) and the MTtable in that interface is iterated (line 8). The process continues until all arrays at allIMT slots are full.

Cutumisu - 14

5 JVM Modifications for Code InheritanceIn this Section we describe the localized changes that we made to the SUN JVM

to support multiple code inheritance. If you try to put code in interfaces, a Javacompiler will generate errors. For example, if the code for writeFloat(float)in Section 2 was moved from class DataOutputStream to the interfacerepresenting the code-type OutputCode shown in Fig. 3, a compiler wouldcomplain that there is no method declaration for writeFloat(float) in theDataOutputStream class. We have not yet modified a Java compiler to recognizecode in the interfaces that we use to represent code-types (although we are nowworking on this problem). Instead, a programmer can insert method code intointerfaces using special comments. We have written some scripts that use a standardcompiler like javac. The scripts are described in Section 7. In this Section we willassume that this process is used to put code into interfaces. We wanted to quickly testthe scientific feasibility of code in interfaces to support multiple code inheritancewithout the engineering effort of modifying a compiler. After discovering that ouridea worked, we began the process of modifying a java compiler and themodifications are proceeding smoothly.

5.1 JVM Loader Modifications

To support code in interfaces, we modified the JVM code that constructs the IMTtable in the class loader that was described in the previous Section:

13A. if (imb.code <> null) // code in interface13B. currentmb = class.vmt[vmtIndex];13C. if (currentmb.code == null) // no code in MT13D. class.vmt[vmtIndex] = imb; // point VMT to imb13E. else // potential code ambiguity13F. if ((! currentmb.class.imt.contains(imb)) &&13G. (!imb.class.imt.contains(currentmb)))13H. throw ambiguous method exception13I. end if13J. end if13K. end if

After a VMT index is inserted into the array of an entry in the IMT table, thecorresponding VMT table entry is checked. If the VMT table points to a method-block in an MT that has no code, then the VMT table entry is changed to point to amethod-block in the MT of the interface that contains the code. However, it ispossible that the method code is ambiguous, as discussed in the next Subsection.

The resolution and dispatch of invokevirtual proceeds in exactly the same way aswith the unmodified JVM, but the change in the class loading code allows the code inthe interface to be found and executed. With the design choices we made, no otherJVM changes were required to support code in interfaces and only one other changewas needed in the JVM to support super calls and it is described in Section 5.6.However, we did encounter one other problem with code in interfaces that was solvedwithout modifying the JVM.

Cutumisu - 15

When an expression containing this as a method argument is compiled, itgenerates an invokevirtual byte-code. However, if such an expression appears in amethod that is in an interface, we need to generate an invokeinterface byte-codeinstead. Since we currently do not use a modified compiler, the scripts described inSection 7 perform this byte-code replacement and no changes to the JVM arerequired.

5.2 Dispatch scenarios

We have analyzed situations that use code in interfaces to ensure that themodified ConstructIMT algorithm works. The four scenarios in Fig. 5 representthe common situations. All other more complex scenarios, can be expressed in termsof these four. In these scenarios, the interfaces that contain code all represent code-types. All interfaces that are above these code-types are omitted.

Fig. 5 Multiple-Inheritance Scenarios

ClassA

InterfaceAalpha()

ClassB

InterfaceA

InterfaceB

alpha()

ClassB

InterfaceA InterfaceBalpha() alpha()

ClassAInterfaceB

InterfaceA

alpha()

alpha()

ClassB

Scenario 1 Scenario 3

Scenario 2 Scenario 4

interface

class

implemened by

subclass

subinterface

Legend

alpha()

Cutumisu - 16

Scenario 1. This is the simplest situation where a class inherits method code from itsimmediate superinterface.Scenario 2. In this case, step 13C is first executed with currentmb bound to amethod-block in ClassB (with no code) and imb bound to a method-block inInterfaceB. with code. This means that step 13D is executed to re-bind the VMTentry to the method-block in InterfaceB. The second time that step 13C isexecuted, currentmb is bound to a method-block in InterfaceB (with code) andimb is bound to a method-block in InterfaceA (with code). Step 13F is enteredsince there is chance for method ambiguity. However, since InterfaceA is a super-interface of InterfaceB, the condition in step 13F evaluates to false and anambiguous method exception is not thrown.Scenario 3. Since either the code in InterfaceA and InterfaceB could beinherited, the programmer is required to declare a method in ClassC to resolve theinheritance conflict [18].Scenario 4. This scenario illustrates an interesting situation where one might concludethat an ambiguous method exception should be thrown for an alpha() in ClassB.However, since the code for alpha() in InterfaceA is reachable from ClassBalong at least one path (by going through InterfaceB), a weaker definition ofinheritance conflict would dispatch the version of alpha() from InterfaceA[19].

5.3 Exploiting Miranda Methods

If there is a declaration for writeFloat(float) in InputCode, thismethod must be understood by any of the classes which implement InputCode.Therefore, there must be a slot for writeFloat(float) in the VMT of eachclass. The slots can be obtained by either of two methods.

The javac compiler can generate methods in each class for all interface methodsthat are contained in all interfaces that are implemented by the class. Such generatedmethods are called Miranda methods. They were added because early VMs did notlook for methods along the interface path, performing the lookup only along thesuperclass chain. Our compiler generates Miranda methods, so no changes needed tobe made to the loader to extend the VMTs.

If a compiler does not generate Miranda methods, one additional action isrequired at class load time. For each interface from a class's IMT, loop through itsmethods and look for corresponding methods in that class's VMT. If one is not found,then extend that class's VMT with this method and make it point to the code in thecurrent interface method.

5.4 Super Calls

The implementation of an overridden method often invokes the same method inthe superclass. In Java, the syntax for a super call is super.alpha(). Withmultiple code inheritance, this call could be ambiguous. C++ solves this problem byspecifying a method in a particular superclass at compile time. For example, eitherA::alpha() or B::alpha(), can be used if A and B are both superclasses of the

Cutumisu - 17

class where this super call appears. In fact, if no definition for alpha() occurs inclass A, then the call A::alpha() would start a dynamic lookup in A, but may findthe appropriate method in a superclass of A.

We have currently implemented the C++ semantics for super calls in multiplecode inheritance Java. Section 7 describes the syntax used to implement this ideawithout changing the Java language. In this Section we use the notationsuper(Start).alpha(), where Start refers to any superinterface. Themodified JVM looks for code in the specified interface and then continues along thesuper-interface chain. If a stricter form of multi-super is required, the start interfacecould be restricted to be an immediate super-interface of the class or interface thatincludes the super call. Some would argue that the C++ model provides too muchfreedom in super calls and this modified semantics would be better.

5.5 Examples of Multi-Inheritance super

Consider the classes and interfaces in Fig. 6. All of the interfaces shownrepresent code-types. InterfaceC is a code-type that does not contain animplementation of alpha(). However, it does contain implementations of othermethods that are not shown. Otherwise there would be no reason to have it there. Thecall super(InterfaceA).alpha(), in a method of ClassE invokes thealpha() in InterfaceA. The call super(InterfaceC).alpha() invokesthe alpha() in InterfaceB. The call super.alpha()invokes the alpha()in ClassD since we do not change the meaning of the single-inheritance super call.

Fig. 6 Examples of Super Calls

Now consider the interfaces and classes of Fig. 7. The callsuper(InterfaceG).alpha(), in a method of ClassM invokes the alpha()in InterfaceF. The traditional call super.alpha() would not find thealpha() in InterfaceJ and in fact would result in a compile-time error sincethere is no alpha() declared in the superclass chain of ClassM. This maintainscompatibility with existing programs. However, if there was also an alpha() inClassK, then an inheritance conflict exception would have been thrown whenClassL was loaded. In fact, this ambiguity could be found by a compiler, but sincewe do not have a compiler yet, we find it at load time.

ClassE

InterfaceA InterfaceCalpha()

InterfaceBalpha()

alpha()

ClassDalpha()

... alpha() {

...super(?).alpha();

Cutumisu - 18

Fig. 7 More super calls

5.6 Implementation of super Calls

Our implementation of the multiple-inheritance super call ,super(Start).alpha() , generates an invokeinterface instead of aninvokespecial that is generated by a normal super.alpha() call. However, thisinvokeinterface call-site is also marked in a special way. We modified the JVM codeto check for this mark and if it appears, to perform a multi-inheritance super insteadof a normal invokeinterface. With compiler support, we could mark the call-site byusing a new byte-code (invokemultisuper). We will refer to this operation as aninvokemultisuper, even when it is represented by a marked invokeinterface. Everyinvokeinterface bytecode is followed by four operand bytes as described in Section4.2. The first two bytes form an index into the constant pool where a symbolicmethod reference is stored. The method reference normally contains the name of thestatic class of the receiver. In the invokemultisuper case, we replace this name by thename of the start interface. The method reference also contains the signature of theinvoked method and this is not changed. The next operand byte is the number ofarguments (nargs) of the method. We use this operand byte to mark aninvokemutisuper by setting its value to 255. The way that it is set by our compilationscripts, is described in Section 7.2. We do not need this byte to record the number ofarguments, since we can obtain the number of arguments from the resolved methodblock instead. We will show how this is done at the end of this Section. The lastoperand byte is for the guess index, described in Section 4.2, and no changes aremade to it for an invokemultisuper call-site.

At first glance, it appears that two JVM changes are required to supportinvokemultisuper, one in resolution and one in computing the execution method-block. In fact, resolution does not change. That is, invokeinterface resolution finds theappropriate resolution method-block for invokemultisuper. However, executionmethod-block computation is different for invokemultisuper. An invokeinterface usesa guess and the resolved method-block stored in the quicked byte-codes to find theexecution method-block using Formula 2. For invokemultisuper, we can just use theresolved method-block directly as the execution method-block since the resolved

ClassMalpha()

InterfaceG

InterfaceF alpha()

InterfaceHalpha()

ClassL

InterfaceJalpha()

ClassK

... alpha() {

...super(?).alpha();

Cutumisu - 19

method-block is guaranteed to be either the method-block of the interface that is citedat the call-site or the first parent interface that contains code.

Since resolution is unchanged, a normal invokeinterface call-site and our markedinvokeinterface call-site both get quicked in the same way. Therefore, the only changewe needed to make in the JVM was at the code that interprets an invokeinterfacequickinstruction. We have marked the changed lines with the words ADDED andREMOVED. All other lines are unchanged. Note that pc[1] and pc[2] are theoperands that form an index into the constant pool where the address of the resolvedmethod block is stored. Also pc[3] is the nargs operand and pc[4] is the guessoperand (not used in the code that is shown).

case opc_invokeinterface_quick:imb = contant_pool[GET_INDEX(pc + 1)].mb;interface = imb.class;offset = imb.offset;. . .// We change the code so that nargs is retrieved// from the resolved interface method-block imb// instead of from the nargs bytecode (pc[3])// arg_size = pc[3]; REMOVEDarg_size = imb.args_size; // ADDEDoptop -= args_size;. . .// We use the third operand (nargs) as a marker for the// multisuper case.if (pc[3] == 255) // ADDED

mb = interface.MT[offset]; // ADDEDgoto callmethod; // ADDED

end if // ADDED. . .

end case

Note that nargs could be obtained from the resolved interface method-block, imb,for a regular invokeinterfacequick instruction as well, so it is not really needed as anoperand in the invokeinterfacequick or invokeinterface instructions. However, wehave taken advantage of its existence to use it to mark our invokemultisuperinstruction. The guess opcode is not used by invokemultisuper, but it is used by aregular invokeinterfacequick.

6 Validating our Modified JVMWe ran two large single-inheritance Java programs on the unmodified JVM and

on our modified JVM. We wanted to verify that our modified JVM did not introduceerrors into single-inheritance programs. We also wanted to measure the performanceoverhead of using our modified JVM on single inheritance programs. The testprograms were javac and jasper [20]. In the first experiment we compiled all of thefiles in the io package. In the second experiment we applied jasper to all of the classfiles in the io package. In both cases, the output using our modified JVM wasidentical to the output using java. In addition, there was no measurable change in the

Cutumisu - 20

execution times. We then ran programs whose inheritance structures are representedin Fig. 5, to test the basic implementation of multiple-inheritance and obtained theexpected results. To test our implementation of super calls, we ran programs with allof the inheritance structures in Fig. 6 and Fig. 7. As a final test, we ran test programsthat used the re-designed java.io library that is shown in Fig. 3 and described inTable 2 and Table 3. These re-factored library classes exercise all of the multiple codeinheritance implementation changes that we made. The test programs ran flawlesslyand with negligible time penalties for multiple-code inheritance.

7 Syntax Support for CompilationThe ability to support multiple code inheritance introduces two challenges to

compilation. First, current Java compilers do not support executable code ininterfaces. Second, a mechanism is needed to handle generalized super calls.

We have developed a translation process that uses an unmodified Java compiler.Our technique is based on source-to-source and class-file-to-class-file transformationsusing custom scripts, publicly available Java tools, and syntactic conventions in theuser's Java code. The process is automated:

1. The programmer includes code in the interface, but the code is withincomments with a special label.

2. Our scripts transform the .java file for the interface into a .class file thatcontains the code. We make use of the tools jasper [20] and jasmin [21].

3. Multi-inheritance super calls are written as two standard Java instructionsand our scripts translate them into the marked invokeinterface instructionsdescribed in Section 5.6.

7.1 Code in Interfaces

Current Java compilers do not allow code to be included in interfaces so theprogrammer delimits the code using special comment delimiters /* MI_CODE andMI_CODE */. For example, consider the interface (code-type) OuputCode and theclass DataOutputStream from Fig. 4. The code for writeFloat(float) thatwas promoted to the interface (code-type) OuputCode is:

interface OutputCode { ...

public final void writeFloat(float v) throws IOException;/* MI_CODE

{ writeInt(Float.floatToIntBits(v)); } MI_CODE */ ...} /* OutputCode */

The goal of our compilation process is to create a file OutputCode.class withJava bytecodes for the body of the method writeFloat(float).

Cutumisu - 21

Our script accomplishes this by creating both an interface OutputCode and aclass with the same name, but followed by _MI and then combining the .class filesof both the interface and class into a single .class file that is like an interface,except that it contains code. Therefore step 2 of our process is divided into severalsub-steps that use several translation tools and scripts and this process is shown inFig. 8.

Fig. 8 The Scripting process for an interface with code

2.1 The interface source file (OutputCode.java) is compiled using astandard javac compiler to create a binary file (OutputCode.class) forthe interface that contains no code.

2.2 The interface binary file (OutputCode.class) is disassembled, using thejasper [20] tool into an interface jasper file (OutputCode.j). The jasperfile is a human-readable form of the binary file that includes importantheaders such as the fact the file was originally compiled from an interface.

2.3 Script MI_hybridInterface performs a source-to-source translation from aninterface source file (OutputCode.java) into an abstract class source file(OutputCode _MI.java) in which the special comment delimiters areremoved from the interface's methods (writeFloat(float)), makingthe code visible to a compiler. The class (OutputCode_MI) is madeabstract to avoid irrelevant compiler error messages since some interfacemethods may not contain code and a class that contains at least one methodwithout code (abstract method) should be declared abstract.

2.4 The abstract class source file (OutputCode_MI.java) is compiled byjavac into an abstract class binary file (OutputCode_MI.class) that

OutputCode.java

OutputCode.class OutputCode_MI.java

2.1 javac 2.3 MI_hybridInterface

OutputCode.j

OutputCode_MI.class

OutputCode_MI.j

OutputCode.j

OutputCode.class

2.2 jasper

2.4 javac

2.5 jasper

2.6 MI_copyHeaderInterface

2.7

Cutumisu - 22

contains code for all of the methods in the original interface that had code(writeFloat(float)).

2.5 The abstract class binary file (OutputCode_MI.class) is disassembledinto an abstract class jasper file (OutputCode_MI.j) using the jaspertool.

2.6 Script MI_copyHeaderInterface first handles the problem of translating call-sites whose receiver is this. It replaces all invokevirtual byte-codes whosestatic types have a suffix _MI with invokeinterface byte-codes in the abstractclass jasper file (OutputCode_MI.j) Due to the difference in the numberof operands required by invokevirtual (two) and invokeinterface (four), twoextra operands are added. However these operands are actually ignoredduring resolution and the operand slots are used during byte code quicking tohold the number of method arguments and the guess as described in Section4.2. Therefore two zero bytes are inserted. The script also removes all of the_MI suffixes of all references in the abstract class jasper file(OutputCode_MI.j). It then combines this modified abstract class jasperfile (OutputCode_MI.j) with the interface jasper file (OutputCode.j)to obtain a hybrid jasper file that has the header of an interface(OutputCode.j) and the code for the methods (OutputCode_MI.j),but no constructors. The hybrid jasper file overwrites the interface jasper file(OutputCode.j).

2.7 The hybrid jasper file (OutputCode.j) is assembled into a hybrid binaryfile (OutputCode.class) using the jasmin [21] tool. Since jasmin is nota complete compiler, it does not explicitly check whether or not interfaceshave code so no errors are reported.

Although there are seven steps in this process, they are hidden from the programmerwho uses the simple comment syntax shown previously. Currently, when a programthat has code in interfaces is executed by java, the verifier must be turned off(noverify flag). We plan to modify our JVM to remove only the verification code forinterfaces so the rest of verification can be maintained.

7.2 Super Calls to Classes and Interfaces

In Section 5.3, we described multi-inheritance super calls and used the syntaxsuper(Start).alpha(). Our scripting approach currently uses two standardJava statements to represent this language extension. To make a multi-inheritancesuper call, the programmer inserts a special static method call that contains the startinterface as an argument, followed by a standard super method call. For example, hereis the current syntax for a super call from the class DataOutputStream to itssuper-interface (code-type), OutputCode:

public final void writeInt(int v) throws IOException {MI.supercall("OutputCode");super.writeInt(v);this.incCount(4);

}

Cutumisu - 23

MI is new library class specifically designed to provide syntax support for multiple-inheritance. It can be discarded once compiler support is developed for multiple-inheritance using the syntax super(Start).alpha().

There is a multi-step compilation process that translates the syntax of our supercalls, to the byte codes specified in Section 5.6. These steps are the sub-steps of step 3of the high-level compilation process presented at the beginning of this Section. Ineach step, the term current class, refers to the class that contains the super call. Theexample used is the code for method writeInt(float) from classDataOutputStream that was given earlier. This process is shown in Fig. 9

Fig. 9 The scripting process for a class containing a super call.

3.1 Script MI_preprocessClass transforms the current class source file(DataOutputStream.java) into an abstract class source file(DataOutputStream_MI.java) by adding the abstract modifier tothe class. At the same time, the super keyword is replaced by the keywordthis in all call-sites that are immediately preceded by an MI.supercall.These two changes will prevent the compiler from generating a spuriouserror when it compiles the code. If the super keyword is not changed tothis, the compiler would require an implementation of the called method(writeInt(int)) in the superclass and there may not be one since weare calling super on an interface (code-type). However, changing thekeyword from super to this means that the current class must have animplementation of the called method (writeInt(int)). In general thisis not always the case since a super call may be made to a different method(e.g. calling superOnly(int) instead of writeInt(int) from insidewriteInt(int)). By making the current class (DataOutputStream)

3.1 MI_preprocessClass

DataOutputStream.java

DataOutputStream_MI.java

DataOutputStream_MI.class

DataOutputStream_MI.j

3.2 javac

3.3 jasper

DataOutputStream.j

3.4 MI_abstractToConcreate

DataOutputStream.class

3.5

Cutumisu - 24

abstract, no compiler error will be generated after the super keyword isconverted to this as long as the interface contains a definition of the calledmethod.

3.2 The abstract class source file (DataOutputStream_MI.java) iscompiled into an abstract class binary file(DataOutputStream_MI.class) using javac.

3.3 The abstract class binary file (DataOutputStream_MI.class) isdisassembed into an abstract class jasper file(DataOutputStream_MI.j) using jasper.

3.4 The script MI_AbstractToConcrete translates the abstract class jasper file(DataOutputStream_MI.j) into a concrete class jasper file(DataOutputStream.j). The abstract class modifier is removed andevery invokevirtual instruction after an MI.supercall method invocationis changed to an invokeinterface instruction. As described in scripting step2.6, two extra bytecode operands are added in converting an invokevirtual toan invokeinterface. In this case, the first extra operand (nargs) is set to 255 tomark this call-site as an invokemultisuper. The argument ("DataOutput")of the MI.supercall is copied over the static type of the receiver of thistransformed (invokevirtual to invokeinterface) bytecode.

3.5 The concrete class jasper file (DataOutputStream.j) is assembled intoa concrete class binary file (DataOutputStream.class) using jasmin.

The same process works on an interface source file that contains a super call.Although there are five steps in this process, they are hidden from the programmerwho uses the simple syntax for a super call.

8 ConclusionsWe have shown why multiple code inheritance is desirable in Java. We have

proposed a mechanism to support multiple code inheritance, through code in specialinterfaces that represent code-types. We have defined and implemented a super callmechanism that resembles the one in C++, where programmers can specify aninheritance path to the desired super interface (code-type) implementation. We haveprovided a comment notation for including code in interfaces and a simple notationfor super calls that does not require compiler support. We have created some scriptsthat translate code in interfaces and supercalls so that they can be compiled by astandard Java compiler. We have modified a JVM to support multiple codeinheritance. Our modifications are small and localized. The changes consist of:

1. The changes to algorithm ConstructIMT executed by the class loader asshown in Section 4.2.

2. The changes to the execution of the invokeinterfacequick bytecode torecognize a marked invokemultisuper that are shown in Section 5.6.

Our implementation does not affect the running time or results of standard Javaprograms and adds negligible overhead to programs that use multiple-inheritance.

Cutumisu - 25

References

1. Y. Leontiev, M. T. Özsu, and D. Szafron , On Separation between Interface,Implementation and Representation in Object DBMSs, 26th Technology of Object-Oriented Languages and Systems Conference (TOOLS USA98), Santa Barbara, August1998, 155 - 167.

2. R. Bretl, D. Maier, A. Otis, J. Penney, B. Schuchardt, J. Stein, E. H. Williams, and M.Williams. The GemStone data management system. In Won Kim and Frederick H.Lochovsky, editors, Object-Oriented Concepts, Databases and Applications, Chapter 12.Addison-Wesley, 1989.

3. C. Lécluse, P. Richard, and F. Vélez. O2, an object-oriented data model. In FrançoisBanchilon, Claude Delobel, and Paris Kanellakis, editors, Building an Object-OrientedDatabase System: The Story of O2, 1992.

4. D. Fishman. Overview of the Iris DBMS. In Won Kim and Frederick H. Lochovsky,editors, Object-Oriented Concepts, Databases and Applications, pages 219–250. Addison-Wesley, 1989.

5. W. R. LaLonde and J. Pugh. Subclassing ≠ subtyping ≠ is-a. Journal of Object-OrientedProgramming, 3(5):57–62, January 1991.

6. A. Taivalsaari. On the notion of inheritance. ACM Computing Surveys, 28(3):439–479,September 1996.

7. C. Chambers and G. T. Leavens. Typechecking and modules for multimethods. ACMTransactions on Programming Languages and Systems, 17(6):805–843, November 1995.

8. C. Chambers and G. T. Leavens. BeCecil, A core object-oriented language with blockstructure and multimethods: Semantics and typing. In FOOL 4, The Fourth InternationalWorkshop on Foundations of Object-Oriented Languages, Paris, France, January 1997.

9. R. K. Raj, E. Tempero, H. M. Levy, A. P. Black, N. C. Hutchinson, and E. Jul. Emerald: Ageneral-purpose programming language. Software Practice and Experience,21(1):91–118, January 1991.

10. C. Szypersky, S. Omohundro, and S. Murer. Engineerig a programming language: Thetype and class system of Sather. Technical Report TR-93-064, The International ComputerScience Institute, November 1993.

11. M. Franz. The programming language Lagoona — A fresh look at object-orientation.Software — Concepts and Tools, 18:14–26, 1997.

12. M. Day, R. Gruber, B. Liskov, and A. C. Myers. Subtypes vs where clauses: Constrainingparametric polymorphism. Proc. 10th ACM Conf. OOPSLA, pub. In SIGPLAN Notices,30(10):156–168, October 1995.

13. Y.Leontieve, T. M. Özsu and D. Szafron. On Type Systems for Database ProgrammingLanguages. ACM Computing Surveys, 34(4):to appear, December 2002.

14. M. Mohnen, Interfaces with Skeletal Implementations in Java, 14th European Conferenceon Object-Oriented Programming (ECOOP'00), Poster Session, June 12th - 16th 2000,Cannes, France, http://www-i2.informatik.rwth-aachen.de/~mohnen/PUBLICATIONS/ecoop00poster.html has a link to an unpublishedfull paper.

15. M. Ellis and B. Stroustrup, The Annotated C++ Reference Manual, Addison Wesley, NewJersey, 1990.

16. C. Dutchyn, P. Lu, D. Szafron, S. Bromling and W. Holst, Multi-Dispatch in the JavaVirtual Machine: Design and Implementation, Proceedings of 6th Usenix Conference on

Cutumisu - 26

Object-Oriented Technologies and Systems (COOTS'2001), January 2001, San AntonioUSA, pp. 77-92.

17. L. Peter Deutsch and Alan Schiffman. Efficient implementation of the smalltalk-80 system.In Principles of Programming Languages, Salt Lake City, UT, 1994.

18. W. Holst, and D. Szafron, A General Framework for Inheritance Management andMethod Dispatch in Object-Oriented Languages, ECOOP'97 Object-OrientedProgramming 11th European Conference, Finland, Lecture Notes in Computing Science1241, Springer Verlag, June 1997, 276-301.

19. C. Pang, W. Holst, Yuri Leontiev and D. Szafron, Multi-Method Dispatch Using MultipleRow Displacement, 13th European Conference on Object-Oriented Programming(ECOOP'99), Lisbon, June 1999, 304-328.

20. jasper - http://www.angelfire.com/tx4/cus/jasper

21. jasmin - http://mrl.nyu.edu/~meyer/jvm/