mci-java: a modified java virtual machine approach to...

13
1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code Inheritance Maria Cutumisu, Calvin Chan, Paul Lu and Duane Szafron Department of Computing Science, University of Alberta {meric, calvinc, paullu, duane}@cs.ualberta.ca Abstract Java has multiple inheritance of interfaces, but only single inheritance of code via classes. This situation results in duplicated code in Java library classes and application code. We describe a generalization to the Java language syntax and the Java Virtual Machine (JVM) to support multiple inheritance of code, called MCI-Java. Our approach places multiply-inherited code in a new language construct called an implementation, which lies between an interface and a class in the inheritance hierarchy. This extension is implemented by making minimal changes to the Java syntax, small changes to a compiler (IBM Jikes), and modest localized changes to a JVM (SUN JDK 1.2.2). 1 Introduction Three distinct language concepts are used in object- oriented programs: interface, code and data. A motivation for separate language mechanisms to support these concepts has appeared [13]. The goal of the research described in this paper is to explicitly support each of these three mechanisms in an extended Java language, to evaluate the utility of concept separation, and to potentially increase demand for separate language constructs in future languages. Researchers and practitioners commonly use the terms type and class to refer to six different notions: a real-world concept (concept) a programmatic interface (interface) The code for an interface (implementation) an internal machine (representation) data layout a factory for creation of instances (factory) a maintainer of the set of all instances (extent) Unfortunately, most object-oriented programming languages do not separate these notions. Each language models the concept notion by providing language constructs for various combinations of the other five notions. 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. In this paper we will focus on general-purpose programming languages, so we will not discuss the extent notion, which is most often used in database programming languages [15]. We combine concept with interface, to enforce encapsulation. We also combine representation and factory , since representation layout is required for creation. Therefore, we reduce the programming language design space to three dimensions: An interface defines the legal operations for a group of objects (interface) that model a concept. An implementation associates generic code with the operations of an interface (implementation) without constraining the data layout. A representation defines the data layout (representation) of objects for an implementation, provides accessor methods for this data and provides a mechanism for object creation (factory). We use the generic term, type to refer to an interface, an implementation or a representation. Inheritance allows properties (interface, implementation or representation) of a type to be used in child types called its direct subtypes. By transitivity, these properties are inherited by all subtypes. If type B is a subtype of type A, then A is called a supertype of type B. If a language restricts the number of direct supertypes of any type to be one or less, the language has single inheritance . If a type can have more than one direct supertype, the language supports multiple inheritance. Interface inheritance allows a subtype to inherit the interface (operations) of its supertypes. The principle of substitutability says that if a language expression contains a reference to an object whose static type is A, then an object whose type is A or any subtype can be used. Interface inheritance relies only on substitutability and does not imply code or data inheritance. Implementation (code) inheritance allows a type to re-use the implementation (binding between an operation and code) from its parent types. Code inheritance is independent of data representation, since many operations can be implemented by calling more basic operations (e.g. accessors), without specifying a representation, until the subtypes are defined. Java and Smalltalk only have single code inheritance, but C++ has multiple code inheritance.

Upload: others

Post on 31-Oct-2019

22 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

1

MCI-Java: A Modified Java Virtual Machine Approach to Multiple CodeInheritance

Maria Cutumisu, Calvin Chan, Paul Lu and Duane SzafronDepartment of Computing Science, University of Alberta

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

Abstract

Java has multiple inheritance of interfaces, but only single inheritance of code via classes. This situation resultsin duplicated code in Java library classes and application code. We describe a generalization to the Java languagesyntax and the Java Virtual Machine (JVM) to support multiple inheritance of code, called MCI-Java. Our approachplaces multiply-inherited code in a new language construct called an implementation, which lies between aninterface and a class in the inheritance hierarchy. This extension is implemented by making minimal changes to theJava syntax, small changes to a compiler (IBM Jikes), and modest localized changes to a JVM (SUN JDK 1.2.2).

1 Introduction

Three distinct language concepts are used in object-oriented programs: interface, code and data. Amotivation for separate language mechanisms to supportthese concepts has appeared [13]. The goal of theresearch described in this paper is to explicitly supporteach of these three mechanisms in an extended Javalanguage, to evaluate the utility of concept separation,and to potentially increase demand for separatelanguage constructs in future languages.

Researchers and practitioners commonly use theterms type and class to refer to six different notions:

• a real-world concept (concept)• a programmatic interface (interface)• The code for an interface (implementation)• an internal machine (representation) data layout• a factory for creation of instances (factory)• a maintainer of the set of all instances (extent)

Unfortunately, most object-oriented programminglanguages do not separate these notions. Each languagemodels the concept notion by providing languageconstructs for various combinations of the other fivenotions. Java uses interface for interface. However, itcombines the notions of i m p l e m e n t a t i o n,representation and factory into a class construct.Smalltalk and C++ have less separation. They use thec l a s s construct for interface , implementation,representation and factory. In this paper we will focuson general-purpose programming languages, so we willnot discuss the extent notion, which is most often usedin database programming languages [15].

We combine concept with interface, to enforceencapsulation. We also combine representation andfactory, since representation layout is required forcreation. Therefore, we reduce the programminglanguage design space to three dimensions:

• An interface defines the legal operations for agroup of objects (interface) that model a concept.

• An implementation associates generic code with theoperations of an interface (implementation)without constraining the data layout.

• A represen ta t ion defines the data layout(representation) of objects for an implementation,provides accessor methods for this data andprovides a mechanism for object creation (factory).

We use the generic term, type to refer to an interface, animplementation or a representation.

I n h e r i t a n c e allows properties (interface,implementation or representation) of a type to be usedin child types called its direct subtypes. By transitivity,these properties are inherited by all subtypes. If type B isa subtype of type A, then A is called a supertype of typeB. If a language restricts the number of direct supertypesof any type to be one or less, the language has singleinheritance. If a type can have more than one directsupertype, the language supports multiple inheritance.

Interface inheritance allows a subtype to inherit theinterface (operations) of its supertypes. The principle ofsubstitutability says that if a language expressioncontains a reference to an object whose static type is A,then an object whose type is A or any subtype can beused. Interface inheritance relies only on substitutabilityand does not imply code or data inheritance.

Implementation (code) inheritance allows a type tore-use the implementation (binding between anoperation and code) from its parent types. Codeinheritance is independent of data representation, sincemany operations can be implemented by calling morebasic operations (e.g. accessors), without specifying arepresentation, until the subtypes are defined. Java andSmalltalk only have single code inheritance, but C++has multiple code inheritance.

Page 2: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

2

Table 1 Support for single/multiple inheritance and concept separation constructs in some existing languages.

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 type none / object constructor none / object constructorSather multiple / abstract class multiple /class multiple / classLagoona multiple / category none / methods single / typeTheta multiple / type single / class single / class

Representation (data) inheritance allows a type tore-use the representation (object layout) of its parenttypes. This inheritance is the least useful and causesconsiderable confusion if multiple data inheritance isallowed. Neither Java nor Smalltalk support multipledata inheritance, but C++ does.

Table 1 shows the separation and inheritancecharacteristics of several languages: Java, C++,Smalltalk, Cecil [3] and its ancestor BeCecil [2],Emerald [18], Sather [19], Lagoona [9] and Theta [6].This list is not intended to be complete. A more generaland extensive review of type systems for object-orientedlanguages has been compiled [15]. Although there isgrowing support for the separation of interface fromimplementation/representation, the concepts ofimplementation and representation are rarely separatedat present. We hope to change this. The major researchcontributions of this paper are:

• The introduction of a new language construct calledan implementation into the Java programminglanguage. This construct completely separates thetwo orthogonal concepts of implementation (code)and representation (data).

• A new multi-super call mechanism that generalizescurrent Java semantics, rather than using C++multi-super semantics.

• The first implementation of multiple codeinheritance in Java, based on localizedmodifications to the SUN JDK 1.2.2 JVM, alongwith minor changes to the syntax of Java and to theIBM Jikes 1.5 compiler. Existing programscontinue to work and suffer no performancepenalties.

• A demonstration that multiple code inheritancereduces duplicated and similar code so programconstruction and maintenance are simplified.

Our modified multiple code inheritance compiler(mcijavac), modified JVM (mcijava), the code for all ofthe scenarios that appear in this paper, and the code for

the java.io classes example are available on-line [15]as MCI-Java.

2 Motivation for Multiple CodeInheritance in Java

In this Section we motivate the use of multiple codeinheritance using some classes from the java.iolibrary. Java currently supports multiple interfaceinher i t ance . Cons ide r the Java c l a s sRandomAccessFile (from java.io ) thatimplements the interfaces DataInput andDataOutput , as shown in Figure 11. Since Javasupports substitutability, any reference to aDataInput or DataOutput can be bound to aninstance of RandomAccessFile.

Figure 1. The inheritance structure of some classes andinterfaces from the java.io library.

However, Java does not support multiple codeinheritance. Much of the code that is inRandomAccessFile is identical or similar to code inDataInputStream and DataOutputStream.Although it is possible to re-factor this hierarchy tomake RandomAccessFile a subclass of eitherDataInputStream or DataOutputStream, it is 1 There are actually two other classes in java.io,FilterInputStream and FilterOutputStream, that are notincluded in Figure 1, Figure 2, or Figure 5. They have been omittedfor simplicity and clarity, since they do not affect the abstractionsdescribed in this paper.

DataInputStream DataOutputStream

DataInput DataOutput

RandomAccessFile

OutputStreamInputStream

interface classImplements / represents subclasses

Page 3: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

3

not possible to make it a subclass of both, since Javadoes not support multiple code inheritance.

This causes implementation and maintenanceproblems. One common example is that duplicate codeappears in several classes. This makes programs largerand harder to understand. In addition, code can becopied incorrectly or changes may not be propagated toall copies. There are many examples of code copyingerrors in the literature, in various contexts. For example,code is often cloned (cut-and-pasted) in device driversfor operating systems [4]. If a bug is found in therepeated code, a fix must be applied to each clone.However, if the same code is re-factored into a singleimplementation in an object-oriented inheritancehierarchy, then any bug fix or new functionality wouldonly have to be done once.

2.1 Duplicate Method Promotion

The methods writeFloat(float) andwriteDouble(double) are examples of duplicatemethods that appear in both DataOutputStream andRandomAccessFile. There are also four methodsthat have identical code in DataInputStream andRandomAccessFile.

Once these duplicate methods have been found, howcan code inheritance be used to share them? Figure 1shows that we need a common ancestor type ofDataInputStream and RandomAccessFile tostore the four common read methods and a commonancestor type of DataOutputStream andRandomAccessFile to store the two common writemethods. To share code, this ancestor cannot be aninterface. It also cannot be a class since we would needmultiple code inheritance of classes and Java does notsupport it. In fact, it should be a multiple inheritanceimplementation. Figure 2 shows the common codefactored into two implementations: InputCode andOutputCode. In this approach, an implementationprovides common code for multiple classes.

Figure 2. Adding implementations to Java, for multiplecode inheritance.

The benefit of using implementations to promoteduplicate methods may seem questionable to save onlysix duplicate methods. However, it is not only duplicatemethods that can be promoted higher in the inheritancehierarchy. Multiple code inheritance can also be used tofactor some non-duplicate methods, if they areabstracted slightly. We have used three additional codepromotion techniques to factor non-duplicate methods.

2.2 Prefix Method Promotion

The first additional technique is called the prefixtechnique where an initial class dependent computationis done at the start of the method and the rest of themethod is identical. For example, consider thereadByte() methods shown in Figure 3, from classesDataInputStream and RandomAccessFile.These methods differ only by a single line of code.Figure 3 shows a single common method promoted toan implementation called InputCode, which canreplace both. The source() method is a new methodthat returns this.in for DataInputStream andreturns this for RandomAccessFile. This prefixtechnique can be used to promote seven other similarmethods in the same two classes.

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

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

// This method replaces the previous two, and// is in InputCodepublic final byte readByte() throws IOException{ int ch = this.source().read(); if (ch < 0) throw new EOFException(); return (byte)(ch);}

Figure 3. An example of using the prefix technique topromote methods.

2.3 Super-suffix Method Promotion

The second additional technique is called the super-suffix technique. It can be used to move a number ofsimilar methods from DataOutputStream and

DataInputStream DataOutputStream

DataInput DataOutput

RandomAccessFile

InputCode OutputCodeInputStream OutputStream

interface class

Implements

implementation

Represents Subclasses

Page 4: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

4

RandomAccessFile to the common implementation,OutputCode. For example, consider the methods forw r i t e C h a r ( i n t ) that appear in classesDataOutputStream and RandomAccessFile, asshown in Figure 4.

// The original method in DataOutputStreampublic final void writeChar(int v) throwsIOException {

this.out.write((v >>> 8) & 0xFF); this.out.write((v >>> 0) & 0xFF);

incCount(2);}

// The original method in RandomAccessFilepublic final void writeChar(int v) throwsIOException {

this.write((v >>> 8) & 0xFF); this.write((v >>> 0) & 0xFF);}

// The method in OutputCode that replaces the// one in RandomAccessFile and does most of the// computation for the one in DataOutputStreampublic final void writeChar(int v) throwsIOException { Sink out = this.sink();

out.write((v >>> 8) & 0xFF); out.write((v >>> 0) & 0xFF);}

// The new method in DataOutputStreampublic final void writeChar(int v) throwsIOException { super(OutputCode).writeChar(v); incCount(2);}

Figure 4. Examples of super-suffix methods that can bereused in different classes.

To replace these methods by a common method, wefirst replace the first line of each by a commonabstracted line, analogous to the previous example.However, this abstraction requires the creation of a newinterface, Sink, that contains one abstract method,write(int) . It also requires a method calledsink() to be declared in OutputCode. A defaultmethod with code, return this is created inOutputCode and it is inherited by classRandomAccessFile. The implementation of thismethod is overridden in class DataOutputStreamwith the code, return this.out.

However, there is another problem that must besolved before we can promote writeChar(int).This method has an extra line of code in classDataOutputStream, which does not appear in classRandomAccessFile. Fortunately, we can promoteall lines except for this suffix line into a commonmethod in OutputCode . This eliminateswriteChar(int) from RandomAccessFile.

However, in DataOuputStream we need to includethe missing last line using a classic refinementtechnique that makes the super call shown in Figure 4.

Note that super(OutputCode) is not standardJava. It calls a method in the superimplementation,OutputCode , instead of calling a method in asuperclass. In general, since there may be multipleimmediate superimplementations, the super call must bequalified by one of them. This is one of the standardapproaches to solving the super ambiguity problem ofmultiple inheritance and it will be discussed later in thispaper. We can use this super-suffix technique topromote a total of six similar methods that appear inDataOuputStream and RandomAccessFile.

2.4 Static Method Promotion

The third technique for promoting non-duplicatemethods is called the static elimination technique. Fore x a m p l e , b o t h DataInputStream andRandomAccessFile implement readUTF(). Theclass implementers must have realized that the twoimplementations were identical, so rather than repeatingthe code, they created a static method calledreadUTF(DataInput) and moved the commoncode to th is s ta t ic method in c lassDataInputStream. Then they provided short oneline implementations of r e a d U T F ( ) i nDataInputStream and RandomAccessFile thatcall the static method. Now that we have provided acommon code repository (InputCode) that bothDataInputStream and RandomAccessFileinherit from, we can eliminate the static method bymoving its code to InputCode and eliminate the shortmethods that call this common code, since both classesnow share this common instance method. This is anexample where we did not actually remove repeatedcode. Instead, we replaced one code sharing abstraction(static sharing), that can cause maintenance problems,by a better code sharing mechanism (inheritance).

We conducted an experiment to determine howmuch code from the stream classes of the java.iolibraries could be promoted, if Java supported multiplecode inheritance. Table 2 and Table 3 show a summaryof the method promotion and lines of code promotionrespectively for each of our code promotion techniques.For example, from Table 2 we see that there are 19methods in class DataInputStream. Of these 19methods, 4 were promoted since there are duplicatemethods in class RandomAccessFile. An additional8 methods out of 19 were promoted using the prefixtechnique illustrated in Figure 3.

Page 5: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

5

Table 2 Method decrease in the Java stream classes using multiple code inheritance. The number marked with a *indicates that all but one line of code in the method was promoted so a single line method remained.

Class duplicate prefix super-suffix staticelimination

totalpromoted

method decrease

DataInputStream 4 of 19 8 of 19 0 of 19 1+1* 14 of 19 74%DataOutputStream 2 of 17 0 of 17 6* of 17 0 8 of 17 47%RandomAccessFile 6 of 45 8 of 45 6 of 45 1 21 of 45 47%

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

Class initiallines

extra lines for prefix,super-suffix and staticelimination

net lines after all codepromotion techniques

line decrease

DataInputStream 127 2 42 67%DataOutputStream 84 7 67 20%RandomAccessFile 158 0 93 41%

Finally, one method was eliminated using staticelimination. The instance method was promoted toInputCode and one static method was reduced from40 lines to 1 line. A look at Table 2 shows that thesuper-suffix technique resulted in 6 out of 45 methodsin class RandomAccessFile being promoted. InDataOutputStream, the corresponding 6 methods(marked by an asterisk - * in Table 2), were notcompletely promoted, since a much shorter method wasretained to make the suffix super call and to execute oneor more additional lines of code.

For the line counts, we only counted executablelines and declarations, not comments or methodsignatures. However, more important than the size ofthe reductions is the reduced cost of understanding andmaintaining the abstracted code. Note that even thoughmost of the method bodies of six methods move up fromDataOutputStream to OutputCode , smallmethods remain that make super calls to these promotedcommon “prefix” methods. In Table 3, the third columnindicates the lines that were added for an abstraction(Sink out = this.sink();) or a multi-supercall (super(OutputCode).writeChar(v);).

Figure 5. The revised Stream hierarchy to supportmultiple code inheritance.

Note that this abstraction required the creation ofanother new interface, Source, that is analogous to thenew interface, Sink, that was described earlier. Theresulting inheritance hierarchy for the Stream classes isshown in Figure 5.

3 Supporting Implementations in Java

Since there is no concept of an implementation inJava, we have three choices as to how to introduce itinto Java: as a class (probably an abstract class), as aninterface or as a new language feature. We actually needto make this decision twice: once at the source codelevel and once at the JVM level. We shall see that it isnot necessary for the choice at these two levels to be thesame.

At the source code level, an abstract class seems tobe the obvious choice to represent the implementationconcept. However, our examples in Section 2 clearlyindicate the utility of multiple code inheritance forimplementations. If implementations were representedby classes (abstract or concrete), we would need tomodify Java to support multiple inheritance of classes.This would have the undesirable side-effect ofproviding multiple data inheritance, since classes (evenabstract classes) are also used for representation.Interfaces have the multiple inheritance we want but, ifwe use interfaces to represent implementations at thesource code level, we would lose the use of interfacesfor their original intent – specifications with no code.

Our solution is to introduce a new languageconstruct, called an implementation at the source codelevel. However, at the JVM level, we decided to makeuse of the fact that interfaces already support multipleinheritance. Therefore, we did not introduce a newlanguage concept at this level. Instead, we generalizedinterfaces to allow them to contain code.

DataInputStream DataOutputStream

DataInput DataOutput

RandomAccessFile

InputCode OutputCodeInputStream OutputStream

interface class

Implements

implementation

Represents Subclasses

SinkSource

Page 6: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

6

To implement our solution, we made independentlocalized changes to the compiler and to the JavaVirtual Machine (JVM). Our compiler (mcijavac)compiles each implementation to an interface thatcontains code in the .class file. Our modified JVM(mcijava) supports execution of code in interfaces andmultiple code inheritance. In addition, the JVMmodifications to support multiple code inheritance areexecuted at load-time and the changes that affect multi-super are call-site resolution changes. Therefore, theperformance of our modified JVM is indistinguishablefrom the original JVM. In fact the SUN JDK 1.2.2 JVMuses an assembly-language module for fast dispatch andno changes were made to this module.

Our approach de-couples language syntax changesfrom the JVM support required for code in interfacesand multiple code inheritance. For example, someonecould propose a different language construct and syntaxat the source code level and make different compilermodifications. In fact, our first implementation used asource-to-source translation approach with standardJava syntax and special comments to annotate interfacesthat should be treated as implementations [5].

As long as a compiler or translator produces code ininterfaces, our modified JVM can be used to execute thecode. Similarly, someone can provide an alternate JVMthat supports code in interfaces and use our languagesyntax and compiler to support implementations.

Although implementations support multiple codeinheritance, they do not support multiple datainheritance, since data cannot be declared inimplementations. However, multiple data inheritancecauses many complications in C++. For example, ifmultiple inheritance is used in C++, an offset for thethis pointer must be computed at dispatch time [8].This is not necessary for multiple code inheritance. Atfirst glance, it may appear that the opportunities formultiple code inheritance without multiple datainheritance are few. However, examples like the one inSection 2 exist in the standard Java libraries and manyapplication programs.

4 The Semantics of Implementations

To support implementat ions , we made twofundamental changes to the language semantics: the firstto support multiple code inheritance and the second tosupport multi-super calls.

4.1 Semantics of multiple code inheritance

The twenty-two scenarios and sub-scenarios inFigure 6 represent the common situations for inheritingcode from implementations, including multiple codeinheritance. The circles containing numbers and theletter X can be ignored for now, since they are related to

JVM modifications and are discussed in Section 8.Other more complex scenarios can be composed fromthese scenarios. When a method alpha() is shown ina particular class or implementation, the scenario alsoholds if that method is inherited from a parent type. Forexample, in scenario 5, the alpha() method in classA , may actually be inherited from a parent class orimplementation. That is, the semantics are consistent,regardless of whether a method is declared explicitly ina type or inherited from a supertype.

Some scenarios have two sub-scenarios that differonly in the order of supertypes, such as scenario 7a andscenario 7b. Syntactically, this is accomplished byvarying the lexical order of the implementations. Wehave defined a semantics that is symmetric with respectto order so the results are the same for both scenarios. Insome languages with multiple code inheritance, likeCLOS [1], the order is significant, but not in oursemantics. However, the order is important with respectto the JVM modifications of the sub-scenarios, asdescribed in Section 8, so the sub-scenarios are includedin Figure 6.

Note that when a method alpha() appears in asuperclass, that superclass may actually represent theclass, Object. For example, scenario 5 can be used torepresent the situation where class A represents theObject class and the alpha() method represent thetoString() method.

For the scenarios in Figure 6, consider a call-sitewhere the static type of the receiver is any type(implementation or class) shown in the scenario, thedynamic type of the receiver is class C, and the methodsignature is alpha() . Scenario 0 mirrors thetraditional case, where an abstract method (no code) inan interface or class is inherited in class C. Since ourscenarios assume that the receiver is an instance of classC , some of the scenarios actually produce compilererrors. Such scenarios are marked with an asterisk (*) inthe lower right corner. For example, scenario 0 wouldproduce a compiler error since it would force class C tobe abstract and generate an error when the code tries tocreate an instance of class C. However, it is important tosupport such scenarios in the JVM with the correctsemantics, since these scenarios can occur at run-time, ifclasses are re-compiled in a specific order. For example,scenario 0 can occur if implementation A is firstcompiled with a non-abstract alpha() method, thenclass C is compiled and then implementation A is re-compiled after changing alpha() to be abstract. Ifclass C is not re-compiled (legal in Java), then at run-time the JVM must throw an exception that indicatesthat the code tried to execute an abstract method.

Page 7: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

7

Figure 6. Inheritance scenarios for multiple code inheritance. The circles are explained in Section 8.

For scenarios 1 through 3, the code fromimplementation A is dispatched. The semantics mirrorthe single code inheritance semantics used by classes.Scenario 4 is an example of code inheritancesuspension, where an abstract method in implementationA , blocks class C from inheriting the code fromimplementation B. Scenario 4 mirrors the semantics forcode inheritance from classes.

In Scenarios 5 through 8, class C inherits code froman implementation along one inheritance path and an

abstract method (no code) along a second path. In thiscase we define the code inheritance semantics for classC , to inherit the code (in these cases fromimplementation A). Notice that Scenario 5 directlymirrors the classic case where a class inherits code for amethod from a superclass and implements an interfacecontaining an abstract method with identical signature.Scenarios 8a and 8b illustrate an important principle ofcode inheritance suspension – an abstract method in atype can only suspend code inheritance along a path

classimplementation Inheirts = extends, subclasses or utilizesconcrete method abstract method

A

C

Scenario 0

alpha()

1

A

C

Scenario 1

alpha()

1

A

C

Scenario 2

B

alpha()

1

B

C

Scenario 4

A

alpha()

alpha()

0

1

A

C

alpha()

Scenario 7a

Balpha()

1 1

Scenario 8a

A

C

B

alpha()

alpha()

1

1

Scenario 17

A

C

D

alpha()

B

1

B

C

alpha()

Scenario 7b

A alpha()

1 0

Scenario 8b

A

C

B

alpha()

alpha()

1

0

Scenario 12b

B

C

A alpha()

alpha()

1

1

Scenario 15b

alpha()

B

C

D

alpha()

A

1

1

B

C

Scenario 3

A

alpha()

alpha()

1

0

Scenario 12a

B

C

Aalpha()

alpha()

1

0

Scenario 14

alpha()D

B

C

A

alpha()

2

0

Scenario 15a

alpha()

B

C

D

alpha()

A

1

0

Scenario 16

B

A

C

D

alpha()

0

alpha() A

C

alpha()

Scenario 10

B

1 3

B

C

Aalpha()

Scenario 5

alpha()

0X

A

C

B alpha()

Scenario 6

alpha()

2X

alpha() A

C

alpha()

Scenario 9

B

3X

Scenario 11

B

C

Aalpha()

alpha()

0

X

Scenario 13

alpha() A

B

C

D

alpha()

0

X

* *

* *

Page 8: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

8

from a parent type through that type; it cannot suspendcode inheritance along all paths from its parent type.

In each of Scenarios 9 and 10, a multiple codeinheritance ambiguity exists between two differentimplementations of alpha() in two parent types ofclass C. Therefore, the programmer is required to supplya local implementation of method alpha() in class Cto clear this ambiguity. If the method in one of theparent types is desired, a method that makes a singlesuper call to the appropriate parent can be used. Again,the order of inheritance is ignored and there is nopreference for inheritance from a superclass overinheritance from a superimplementation.

Scenarios 11 through 15 are quite interesting cases.Two different multiple inheritance semantics could bedefined for our language extension [17]. Strong multiplecode inheritance semantics requires these scenarios tobe inheritance ambiguities, since for each scenario, classC can inherit different code along different codeinheritance paths. However, relaxed multiple codeinheritance semantics states that if two types serve aspotentially ambiguous code sources and are related byan inheritance relationship, the code in the child typeoverrides the code in the parent type. The code in thechild type is called the most specific method. With these

semantics, the inherited code in class C , is the codeprovided by type A, for scenarios 11 through 15. Wehave implemented relaxed multiple code inheritancesemantics in our compiler and JVM. It would be simpleto implement strong semantics instead. In this case, afurther decision would be required to resolve Scenarios16 and 17, since they inherit the same code alongmultiple paths. However, since we used the relaxeddefinition of multiple code inheritance semantics, theseare not ambiguous scenarios and the code fromimplementation A is inherited by class C.

4.2 Semantics of multi-super calls

Even if a method is overridden in a subclass, it isoften desirable to invoke the original method in asupertype. However, due to multiple code inheritance,we have to choose among multiple supertypes in a supercall. We saw an example of this in Figure 4, where themethod writeChar(int) i n c l a s sDataOutputStream needed to call the overriddenmethod code from its s u p e r i m p l e m e n t a t i o nOutputCode, as opposed to calling the method codein its superclass, OutputStream . We call thisgeneralization a multi-super call.

Figure 7. Inheritance scenarios for multi-super.

classimplementation Inheirts = extends, subclasses or utilizesconcrete method abstract method

A

Scenario 0

alpha()

*

C

A

Scenario 1

alpha()

C

A

Scenario 2

B

alpha()

C

B

Scenario 3

A

alpha()

alpha()

C

B

Scenario 4

A

alpha()

alpha()

*C

A alpha()

Scenario 7a

Balpha()

C

Balpha()

Scenario 7b

A alpha()

C

Scenario 8a

A

B

alpha()

alpha()

C

Scenario 8b

A

B

alpha()

alpha()

C

Scenario 12a

B

Aalpha()

alpha()

C

Scenario 12b

B

A alpha()

alpha()

C

Scenario 15a

alpha()

B

D

alpha()

A

C

Scenario 15b

alpha()

B

D

alpha()

A

C

Scenario 17

A

D

alpha()

B

C

alpha() A alpha()

Scenario 10

B

C

*

Page 9: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

9

In C++ each multi-super call is a direct jump to aparticular superclass that is specified lexically in thecode and it is resolved at compile time. If subsequentchanges to the code result in a new class being insertedbetween the class that contains the call-site and thetarget class of the multi-super call, then any code in theintervening classes is ignored. This can result in a logicerror if one or more of the inserted classes adds amethod that performs some additional computations thatare desired.

In the spirit of Java, we have defined a moredynamic semantics for multi-super than the staticsemantics defined for C++. Our modified Java compilerensures that only a direct parent supertype can bespecified in the multi-super call. These multi-supersemantics are consistent with the classic supermechanism of Java, where the lookup always startsfrom the closest superclass and searches upwards for animplementation. If a new superclass is added, the call-site code does not need be changed to take advantage ofany “value-added” code that is inserted in newintervening classes.

Figure 7 shows the basic inheritance scenarios thatdefine the semantics of multi-super. In each scenario,assume that a class or implementation (not shown in thescenario) is a direct subtype of implementation C andmakes a multi-super call to implementation C. Thescenarios in Figure 7 can be derived from the scenariosof Figure 6 by changing class C into implementation C.However, several of the scenarios have been excludedafter this transformation, since it is impossible to have aclass that is a supertype of an implementation.Therefore, scenarios: 5, 6, 9, 11, 13, 14 and 16 fromFigure 6 are excluded. In addition, scenario 10 cannotoccur, since an ambiguous method exception would begenerated when implementation C was loaded. In otherwords, ambiguous super calls can never happen. In eachscenario of Figure 7, the code for method alpha() inimplementation A is executed. Of course, if thisalpha() is abstract, then an exception is thrown. Aswas the case with Figure 6 , any scenario marked withan asterisk will not compile without an error so a seriesof re-compilations is necessary to generate the scenarioat run-time.

Note that Figure 7 does not contain any scenarioswhere a classic super call is made to a superclass, eventhough the code in this superclass may actually beinherited from an implementation. In fact, there aremany such scenarios, since each scenario in Figure 7,could have C as a class instead of an implementation. Inall of these cases, the same semantics holds as if C is animplementation.

5 Syntax and Compiler Changes

We made three minor syntax changes to thelanguage to support the implementation languageconstruct. First , we added the keywordimplementation to mark an implementation. Forexample, the first line of the OutputCodeimplementation shown in Figure 5 is:

public implementation OutputCode implements DataOutput, Sink {

Second, we added the keyword utilizes to marka class that inherits from an implementation. Forexample, the first line of the RandomAccessFileclass shown in Figure 5 is:

public class RandomAccessFile utilizes InputCode, OutputCode {

and the first line of the DataOutputStream classshown in Figure 5 is:

class DataOutputStream extends OutputStream utilizes OutputCode {

Third, we modified the syntax of the super methodcall to implement the multi-super call. We specify oneof many potential implementations that can contain codeor inherit code from other implementations, as anargument. For example, Figure 4 shows a multi-supercall from the method writeChar(int) in classDataOutputStream to the superimplementation ofthis method in implementation OutputCode.

If no code for a method is contained in a referencedsuperimplementation and it has not inherited code fromone of its superimplementations, then the compilergenerates an error, similar to the case of finding no codein a superclass for a normal super call.

Note that each class still has a unique superclass, sothe syntax for a normal super call is unchanged. Forexample, for any method in the classDataOuputStream, the call super.alpha()would still call an implementation of alpha() in thesuperclass of DataOutputStream , which isOutputStream.

To accommodate these three syntax changes, and toreport ambiguous method declarations, as described inSection 4, we modified the open-source IBM Jikescompiler, version 1.15 [10]. There were originally 243C++ classes in the compiler. We modified 17 methodsin 10 of these classes and added an additional 41methods to them. We also added 2 classes used inbuilding abstract syntax trees. Each of these addedclasses consisted of 1 constructor, 1 destructor and 3accessor functions.

Page 10: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

10

All of the changes were straightforward. However,one of the changes was especially interesting: whencompiling a message expression whose receiver is thepseudo-variable, this, the standard compiler alwaysgenerates an invokevirtual instruction. However, if sucha message expression appears in an implementation, itmust generate an invokeinterface instruction instead.

6 Correctness and PerformanceExperiments

This Section provides an overview of tests andexperiments conducted during the process of verifyingour modifications to the Jikes compiler and SUN JVMJDK 1.2.2. The first goal of our validation was to showthat our multiple code inheritance implementationpreserves the semantics and performance of existingsingle inheritance code. The second goal was to showthat both our basic multiple code inheritance and themulti-super call mechanism execute correctly inmultiple inheritance programs.

We first compiled and ran three large existing Javaprograms (javac, jasper [11] and javap [12]) using ourmodified compiler and JVM. In all three of these tests,we obtained correct results and there was no measurablechange in the execution times, between the original andmodified JVMs [5].

We then conducted tests to verify the correctness ofour JVM and compiler modifications for multipleinheritance programs. We constructed test programs foreach scenario described in Section 4 and they producedthe desired results. The scenarios shown in Figure 6 testall paths through the modified class loader code shownin Figure 8. The scenarios in Figure 7 test all pathsthrough the modified multi-super resolution code.

Finally, we conducted an experiment to evaluate therun-time performance of the re-factored I/O classesdescribed in Section 2 that used multiple inheritance,compared to the I/O classes from the standard library.These re-factored library classes exercise all of themodifications that we made to support multiple codeinheritance, including the use of the pseudo-variablethis in an implementation. The test program ranwithout errors and with unmeasurable time penalties formultiple code inheritance. We used two differentconfigurations. The first used an AMD Athlon XP2400+ running Red Hat linux version 7.2. The secondused a SUN Ultra-60 running Solaris version 9.

This test program starts by creating an instance ofRandomAccessFile and writing a series of doubleprecision values, int values, char values and strings to it.This exercises methods specified in the interfaceD a t a O u t p u t whose code appears in theimplementation OutputCode. The data file is thenclosed and re-opened as an instance of

DataInputStream. All of the data is read, usingmethods specified in the interface DataInput, whosecode appears in the implementation InputCode, withhelp from a few methods that remain inDataInputStream. As the data is read, it is writtento a second file using an instance ofDataOuputStream. These writes exercise methodsspecified in DataOutput and implemented inOuputCode. Finally, this file is read using an instanceof RandomAccessFile, exercising methods specified inDataInput and implemented in InputCode.

7 Dispatch in the Unmodified JVM

To implement multiple code inheritance, wemodified SUN's JVM 1.2.2 [20] to execute code ininterfaces. We know of no elegant way to implementmultiple code inheritance in Java without modifying theJVM. Although the approach of using inner classes [16]is interesting, its use of delegation inheritance along theinterface chains is not very appealing from the languageconsistency perspective. Inner classes make interfaceinheritance second class. We have previous successmodifying JVM dispatch to support multi-methoddispatch [7]. Our changes to support multiple codeinheritance are concise and localized and should transferto other JVMs.

In this Section we briefly review how a method call-site is dispatched in the unmodified SUN JVM and thestandard data structures that are used. A more completedescription of these data structures has appeared [5].

At compile-time, a call-site is translated to a JVMinstruction whose bytecodes depend on the static type ofthe receiver object. If the static type is a class, then thegenerated op-code is invokevirtual. If the static type isan interface, then the generated op-code isinvokeinterface. In either case, a method reference isalso stored as an instruction operand – an index into theconstant pool. The method reference contains thesignature of the method and the static type of thereceiver object.

In the SUN JVM, the dispatch process forinvokevirtual, uses three data structures: method block(MB), method table (MT) and virtual method table(VMT). The dispatch process for invokeinterfacerequires one additional data structure, interface methodtable (IMT).

At run-time, the compiled code for each method isreferenced using a method block (MB) that containscomplete information for the method, including itssignature, a pointer to its bytecodes and an offset thatwill be used during dispatch. In the case of interfaces,the bytecode pointer is null, since in standard Javathere can be no code in interfaces. In the SUN JVM

Page 11: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

11

1.2.2 distribution, method dispatch consists of thefollowing three steps:

S1. Method resolution: generates a resolution methodblock .

S2. Method quicking (or pre-execution): replaces theopcode with one of its quick counterparts andcomputes a reference to an execution method block.

S3. Method execution: executes the quicked bytecodeusing the referenced execution method block.

A method table (MT) is an array of MBs that aredeclared (not inherited) in a class or interface. Toresolve an invokevirtual instruction (S1), the JVM usesthe bytecode’s method reference to obtain the staticclass and a method signature. It then searches the MT ofthis static class for an MB whose signature matches. Ifno match is found, it searches the MTs along thesuperclass chain. The compiler guarantees that a matchwill be found and the match is the resolution MB.

The resolved MB will not necessarily be executed.However, it will contain an offset that can be used as anindex into another data structure called the virtualmethod table (VMT), which contains a pointer to theexecution MB. A reference to this execution MB is usedin the quick byte codes that are generated in step 2 (S2)of the method dispatch process. We make nomodifications to steps S2 or S3.

When a class is loaded, the loader constructs an MTand VMT for the class. It constructs a VMT by firstcopying the VMT of its superclass and then extendingthe VMT for any new methods that have been declaredin the class, whose signatures are different from thesignatures of inherited methods. During class loading,the loader may discover that the class needs a VMT slotfor an abstract method for which it does not declare anycode or inherit any code. In this case, the loader extendsthe VMT by providing a slot for this method, allocatesan MB in another table called the Miranda MethodTable (MMT) and sets the VMT slot for the method topoint to this new MB. At the end of this process, everymethod that can be invoked on an instance of the loadedclass, has a unique VMT table entry that points to anMB. We refer to a VMT entry that points to an MB inthe class’s MT or MMT as a local VMT entry. It is alsopossible that a VMT entry points to an MB in the MT orMMT of a superclass. Such an entry is called a non-local VMT entry. This distinction is critical to supportcode in interfaces.

Resolution of an invokeinterface (S1) is similar toresolution for an invokevirtual, except that the methodreference includes an interface instead of a class.Resolution starts at the interface method table (IMT) ofthis interface.

The IMT provides an extra level of indirection thatsolves the problem of inconsistent indexing of interface

methods between classes. This extra level of indirectionis analogous to the way C++ implements multipleinheritance using multiple virtual function tables.

An IMT has one entry for each interface that isextended or implemented (directly or indirectly) by itsclass or interface. This entry contains a pointer to theinterface and a pointer to an array of VMT offsets,where there is one array entry for each method declaredin the interface.

During resolution, the JVM starts with the zero’thentry of the interface's IMT, which contains a pointer tothe interface itself. The MT of this interface is searchedfor a matching method. If one is not found, the MTs ofsubsequent interfaces in the IMT are searched. Thecompiler guarantees that a signature match will befound.

As with the invokevirtual bytecode, the resolutionMB may not be the execution MB. In theinvokeinterface case, the resolution MB contains a localMT offset instead of a VMT index. To use this offset,the JVM first finds the IMT entry for the static interfacetype of the receiver object. This entry contains an arrayof VMT indexes. The offset from the resolution MBselects the array element that contains the appropriateindex into the VMT of the receiver’s class. This VMTentry is the execution MB and a reference to it is used inthe quick bytecodes that are generated in step 2 (S2) ofthe dispatch process.

8 JVM Modifications for Multiple CodeInheritance

In this Section we describe the localized changesthat we made to the SUN JVM to support multiple codeinheritance. Recall that at the source code level, wesupport multiple code inheritance by placing code into anew construct called an implementation. However, ourcompiler produces a .class file that represents thisimplementat ion by an interface with code in itsmethods. Therefore, our changes to the JVM are basedon supporting code in .class files that are labeled asinterfaces.

8.1 Code in Interfaces

Since code from interfaces has to be reachable fromthe class pointer of the receiver object, we modify theIMT construction for a class to copy the code from theinterfaces to a data structure accessible from the class.Since this change only affects JVM class loading codeand does not change any code that is executed at a call-site, its runtime overhead is small.

In the current JVM, when constructing the IMT ofthe loaded class, the JVM iterates over eachsuperinterface of the class. For each interface, the JVMiterates over each declared method. Besides the normal

Page 12: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

12

actions taken in the classic JVM, for each method in aninterface, our modified JVM takes some additionalactions. The algorithm that implements these extraactions is shown in Figure 8. Each scenario from Figure6 is marked in the algorithm to show where it ishandled. Each method in Figure 6 has a circled numberthat shows which action from Figure 8 is taken when itsMB is processed. The circled X indicates that no actionis taken, since that method is in a class instead of aninterface. In the algorithm, the symbol < is used toindicate a proper subtype and >= indicates a supertype.

Let c be the class being loaded.Let imb = the MB of the method being processed.Let mb = the current MB pointed to by the VMT

entry of c with the same signature as themethod being processed.

if (mb.codepointer == null)if(mb is not local(c))

Action 2 //scenarios: 6Aelse if (imb.type > mb.type) and there is no

path from c.type to imb.type that doesnot go through mb.typeAction 0 // scenarios: 4B

elseAction 1 // scenarios: 0, 1, 2A, 3A,4A,

// 7aB, 7aA, 7bA, 8aB, 8aA, 8bA, // 10B, 12aA, 12bB, 15aA, 15bB // 17A

else // mb.codepointer != nullif imb.codepointer == null

Action 0 // scenarios: 5B, 7bB, 8bBelse

if (imb.type < mb.type)if (mb is local(C))

Action 1 // scenarios: // 12bA, 15bA

elseAction2 // scenarios: 14A

else if (imb.type >= mb.type)Action0 // scenarios 3B, 11B, 12aB,

// 13B, 14B, 15aB, 16A,else // imb.type unrelated to mb.type

Action 3 // scenarios: 9A,10A

Action 0: do nothing.Action 1: imb is copied onto mb, but the offsetof mb (index back to the VMT) is retained.Action 2: Create a new MB on the JVM C-heap,copy imb to the new MB, change the current VMTentry (the index of this entry is in the offsetof mb) to point to the new MB and change theoffset of the new MB to this VMT index.Action 3: Throw an ambiguous method exception.

Figure 8. The JVM modifications to support code ininterfaces.

Creating a new MB on the C-heap is necessary whena class inherits code from an interface that overridescode in a non-local MB. The alternative of changing thecode pointer for a non-local MB can result in the wrongcode being executed. For example, consider scenario 14from Figure 6. At the time when class C is being loaded,its VMT entry for alpha() points to a non-local MB

in the MMT of class D. While building the IMT in C,the JVM encounters the method alpha() in interfaceA. If it copied the MB for alpha() from interface A tothe MB for alpha() in C (stored in the MMT of classD), dispatch would work properly for any alpha()message sent to an instance of class C. However,consider the message alpha(), sent to an instance ofclass D . Its VMT entry for alpha() points to themodified MB in its MMT, which points to the code ininterface A (instead of the code from interface B).

It is important to note that resolution and dispatch ofinvokevirtual and invokeinterface bytecodes proceeds inexactly the same way as with the unmodified JVM, butthe change in the class loading code allows the code inthe interface to be found and executed. With the designchoices we made, no other JVM changes were requiredto support code in interfaces. That is, we modified theIMT construction algorithm for a class to:

1. detect and report potential ambiguities, and2. copy the code from interfaces to classes.

8.2 Multi-super calls

To support multi-super calls, we changed theresolution code that is executed the first time that amulti-super call-site is encountered. There are nochanges to the dispatch code, so any multi-super call-site that is executed more than once uses the standardJVM code for subsequent executions. For example, theJVM actually has an assembly language module thatdoes dispatch (instead of using C code). No change tothis assembly language dispatch module is required tosupport our multi-super extension.

A super call is compiled into an invokespecialbytecode, where the method reference contains a targetinterface instead of a class. The JVM can recognize amulti-super call since it is the only case where thecompiler generates an invokespecial bytecode and themethod reference is an interface instead of a class.

Our modified JVM uses a custom resolutionalgorithm to find a resolution MB. The algorithmtraverses all of the interfaces in the IMT of the targetinterface. It finds all MBs whose signature matches thesignature in the method reference. It then computes themost-specific MB as the resolution MB. Our JVM thenfinishes by performing the same bytecode quickingoperation as the unmodified JVM, where the call-site isreplaced by an invokenonvirtualquick bytecode. Nochange is made to the way this quicked bytecode isexecuted (in the assembly language module).

Since resolution happens only once at each call-site,the overhead of our change is insignificant in therunning time of a program, as supported by theperformance experiment described in Section 6.

Page 13: MCI-Java: A Modified Java Virtual Machine Approach to ...webdocs.cs.ualberta.ca/~systems/mci/docs/UsenixVM-20.pdf1 MCI-Java: A Modified Java Virtual Machine Approach to Multiple Code

13

9 Conclusions

We have shown why multiple code inheritance isdesirable in Java. We have defined a mechanism tosupport multiple code inheritance, through code ingeneralized interfaces called implementations and asuper call mechanism, where programmers can specifyan inheritance path to the desired superimplementation.We have defined simple syntactic Java languageextensions and constructed a modified Jikes compiler(mcijavac) to support these extensions. We haveconstructed a modified JVM (mcijava) to supportmultiple code inheritance. Our modifications are smalland localized. The changes consist of:

1. Class loader changes to support code in interfaces.2. Method block resolution changes to support multi-

super.

Our JVM modifications do not affect the running timeof standard Java programs and they add negligibleoverhead to programs that use multiple inheritance.

References

[1] B. Bobrow, D. DeMichiel, R. Gabriel, S. Keene,G. Kiczales, D. Moon. Common Lisp ObjectSystem Specification, X3J13 Document 88-002R,June 1988.

[2] C. Chambers and G. T. Leavens. BeCecil, A coreobject-oriented language with block structure andmultimethods: Semantics and typing. In FOOL 4,The Fourth International Workshop onFoundations of Object-Oriented Languages, Paris,France, Jan. 1997.

[3] C. Chambers and G. T. Leavens. Typecheckingand modules for multimethods. ACM Transactionson Programming Languages and Systems, 17(6),Nov. 1995, 805–843.

[4] A. Chou, J. Yang, B. Chelf, S. Hallem, and D.Engler. An Empirical Study of Operating SystemsErrors. 18th ACM Symposium on OperatingSystem Principles (SOSP), Banff, Alberta, Canada,Oct., 2001, 73–88.

[5] M. Cutumisu. Multiple Code Inheritance in Java,M.Sc. Thesis, University of Alberta, 2003.http://www.cs.ualberta.ca/~systems/mci/thesis.pdf

[6] M. Day, R. Gruber, B. Liskov, and A. C. Myers.Subtypes vs where clauses: Constrainingparametric polymorphism. OOPSLA, Oct. 1995,156–168.

[7] C. Dutchyn, P. Lu, D. Szafron, S. Bromling andW. Holst. Multi-Dispatch in the Java VirtualMachine: Design and Implementation,

Proceedings of 6th Usenix Conference on Object-Oriented Technologies and Sys tems(COOTS'2001), San Antonio, Jan. 2001, 77-92.

[8] M. Ellis and B. Stroustrup. The Annotated C++Reference Manual, Addison Wesley, New Jersey,1990.

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

[10] IBM Research Jikes Compiler Projecthttp://www.research.ibm.com/jikes/

[11] Jasper. http://www.angel re.com/tx4/cus/jasper

[12] Javap.http://java.sun.com/j2se/1.3/docs/tooldocs/solaris/javap.html

[13] Y. Leontiev, M. T. Özsu, and D. Szafron. OnSeparation between Interface, Implementation andRepresentation in Object DBMSs, 26thTechnology of Object-Oriented Languages andSystems Conference (TOOLS USA98), SantaBarbara, Aug. 1998, 155 - 167.

[15] Y. Leontiev, T. M. Özsu and D. Szafron. On TypeSystems for Database Programming Languages.ACM Computing Surveys, 34(4), Dec. 2002, 409 –449.

[15] MCI-Java.http://www.cs.ualberta.ca/~systems/mci.

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

[17] C. Pang, W. Holst, Y. Leontiev and D. Szafron.Multi-Method Dispatch Using Multiple RowDisplacement, 13th European Conference onObject-Oriented Programming (ECOOP'99),Lisbon, June 1999, 304-328.

[18] R. K. Raj, E. Tempero, H. M. Levy, A. P. Black,N. C. Hutchinson, and E. Jul. Emerald: A general-purpose programming language. Software Practiceand Experience, 21(1), Jan. 1991, 91–118.

[19] D. Stoutamire, and S. Omohundro. The Sather 1.1specification. Tech. Rep. TR-96-012, InternationalComputer Science Institute, Berkeley, Aug. 1996.

[20] Sun Microsystems Inc. Java[tm] 2 Platform.http://www.sun.com/software/communitysource/java2/download.html.