A Whitepaper on Java, RMI and CORBA
Prepared by David Curtis
Copyright © 1997 by Object Management Group
Java, RMI and CORBA
The impact of Java on the computing world is beyond doubt; just look at the bookshelves in the computing section of any bookstore, or attend any conference in the software industry. There are good reasons. The near-perfect portability of Java applications is a great boon in a multi-platform world; the ability to download Java applets and the close integration of Java with Web browsers make it an ideal medium for Web- and Internet-based development; its ease of use compared to its most popular object-oriented predecessor, C++, makes it accessible to a much wider range of developers and speeds the development process measurably. Java's praises having been sung, it behooves us to ask, what are its limitations? What role will Java's rising star play in the expanding universe of distributed computing? How will Java coexist with other pre-existing or simultaneously emerging technologies? In particular, what rôles will Java and CORBA play, with respect to each other? Will they compete, or be complementary?
Java and CORBA
Java and CORBA, to a great extent, appear to be made for each other. In their recent book, Client/Server Programming with Java and CORBA, Robert Orfali and Dan Harkey put it this way-
"Java is the first step toward creating an Object Web, but it is still not enough. Java offers tremendous flexibility for distributed application development, but it currently does not support a client/server paradigm. To do this, Java needs to be augmented with a distributed object infrastructure, which is where OMG's CORBA comes into the picture. CORBA provides the missing link between the Java portable application environment and the world of intergalactic back-end services. The intersection of Java and CORBA object technologies is the natural next step in the evolution of the Object Web."
The respective object models of Java and CORBA correspond closely to one another-they both support the notion of abstract interfaces distinct from implementations or classes; CORBA IDL data types map very naturally to Java data types; their interface inheritance mechanisms are nearly identical; CORBA name spaces-modules-map directly onto Java packages; the list could continue. Beyond having highly compatible object models, the architectural roles they play in building systems are naturally complementary. Simply put, Java allows you to create portable objects and easily distribute them; CORBA allows you to connect them together and to integrate them with rest of you computing environment-databases, legacy systems, objects or applications written in other languages, what have you.
What about RMI?
With the release of JDK version 1.1, Java has its own, built-in native ORB, called RMI (Remote Method Invocation). Though RMI is an ORB in the generic sense that it supports making method invocations on remote objects, it's not a CORBA-compliant ORB. RMI is native to Java. It is, in essence, an extension to the core language. RMI depends on many of the other features of Java-object serialization, portable, down-loadable object implementations, and Java interface definitions, among others. The resulting mechanism is very natural for Java programmers to use. They never have to leave the Java programming environment or learn any new "foreign" technology. On the other hand, RMI has some limitations, principle among which is a consequence of its greatest strength-its tight integration with Java makes it impractical for use with objects or applications written in any other language.
The point of this paper is not to discredit RMI; it's a viable alternative to CORBA for some applications. What we want to show is that Java RMI and CORBA each meet a certain set of needs, and are appropriate for a certain range of applications. There is overlap between the two, in that there are applications that could be adequately built with either technology, but there many more applications for which one of the two technologies has distinct advantages over the other. We want to examine what the differences are, and where one technology might be more appropriate than the other.
Programming or Integration?
Java (with RMI by extension) is a concrete programming technology. It is primarily designed to solve the problems of writing and organizing executable code, programs. It achieves this end admirably. As such, it constitutes a specific point in the space of programming technologies. Consider the illustration below.
The chasm that exists between programming languages is always painful to cross. That pain may vary (metaphorically speaking) from that of a hangnail to that of a limb amputation, depending on the languages being used and their relative differences. In this respect, programming technologies are like islands, or peaks separated by deep canyons (Figure 1-A). Building systems in multiple languages requires that you somehow bridge these canyons, which is a non-trivial programming task at best (Figure 1-B). The techniques and skills required depend to a great extent on the particular pair of languages being used together, so that the techniques used to make Java call Ada code are somewhat different from those used to call C++, and so on. This causes the complexity of building systems in a multilingual environment to increase significantly (sometimes non-linearly) with the number of languages being used.
Java supplies an API called JNI, or Java Native Interface, that allows Java code to call and be called by routines in other languages. It is primarily geared toward inter-operating with C and C++ , and it is a rather difficult interface to master. RMI is a Java-to-Java technology. If you want a Java client to use RMI to communicate with a remote object in another language, you must do it by way of a Java intermediary that is co-located with the "foreign" remote object (see Figure 2).
The underlying problem here is that Java is a programming technology that, by definition, works within the boundaries of the languages itself. Using a programming language to solve the problem of crossing gaps between programming languages is like using rats to kill mice-at the end of the day, you still have a rodent problem.
By contrast, CORBA is an integration technology, not a programming technology. It is specifically designed to be the glue that binds disparate programming technologies together. It does not exist as a point in the programming space; by design, it occupies the spaces between the peaks representing individual languages (see Figure 3).
When a Java client uses CORBA technology to communicate with a C++ object, for example, both the C++ programmer are the Java programmer work completely within their respective language environments. The CORBA ORB presents the Java client with a Java stub interface and the C++ programmer with a C++ skeleton interface (see Figure 4). CORBA takes care of the cross-language issues automatically. This picture reflects the fact that CORBA is specifically designed as an integration technology, not a programming technology.
The medium that CORBA uses to perform this integration is OMG IDL (Interface Definition Language). IDL isn't a programming language. It describes interfaces between distributed components. It doesn't depend on any particular programming language technology. From IDL interface descriptions, an ORB product automatically generates code in the language of your choice to effect integration and distribution-the "glue" that connects components and manages communication between them.
You may ask, "why should I have to learn another language (IDL) in order to use CORBA technology ?". First, note that IDL is an extremely simple language. Since it only describes interfaces, almost all of the complex issues faced by programming languages-control flow, memory management, functional composition, and so on-are absent from IDL. Learning and using IDL is trivial in comparison to using a new programming language. Second, having a single descriptive language as the basis for agreeing on interfaces is extremely important. Other approaches, such as the attempt to describe POSIX APIs separately in both C and FORTRAN, usually lead to subtle but troublesome differences in behavior. Finally, IDL can be generated from some programming languages' native interface descriptions. This capability is currently available is some ORB products, such as Visigenic's Caffeine product, or IBM's Direct to SOM compilers. By taking this approach, it is possible to get the benefits of IDL's language neutrality and power as an integration medium without leaving your favorite programming language.
But won't I write everything in Java, anyway?
In light of the programming herd's stampede towards Java, this is a fair question, deserving serious consideration. There are a lot of good reasons for writing programs in Java. Does Java's popularity spell the demise of all other programming languages, for all time?
Not likely. Though Java will undoubtedly have a large share of the market for new software development, there are several reasons why it won't be the only language you will have to accommodate in your systems, including:
- Legacy Systems-There are billions of dollars invested in software written in languages other than Java. In fact, the largest problem faced by most large enterprises in the immediate future is the integration of their existing stovepipe applications, not creating new applications. Most of the new applications being written in corporate IT shops today are not isolated systems, they are subsystems that live in the context of existing legacy systems. In addition to legacy systems, IT organizations also have large investments in legacy tools, legacy application libraries, and-perhaps most troublesome of all-legacy programmers. This railroad train of investment in technology and skills will not be suddenly de-railed by the advent of new language, however titillating it may be.
- Performance-Java's extreme portability is gained, to some extent, at the cost of performance. Java programs are executed by a virtual machine, a machine being simulated by software on your computer. While much can do to improve the performance of execution on a software virtual machine, it will never perform as well as equivalent code executing directly on the hardware; it's a theoretical impossibility. While JIT compilers can potentially reduce these performance penalties by converting the Java bytecode to native machine code, the resulting code is no longer portable, and the cost of compiling the bytecode is only worth paying if the resulting program is executed often enough for the savings to offset that cost.
In addition to execution speed, there is also the matter of predictability. Java eliminates most of the programming problems related to memory management by providing automatic garbage collection. The Java virtual machine continuously executes a low-priority thread that scours memory for blocks that are no longer in use, and returns them to the free memory pool. This is one of Java's major advantages, in terms of programming simplicity, but it also creates performance-related problems. When the memory available to a Java application grows small or runs out, the Java virtual machine is forced to stop processing long enough to collect garbage, i.e., to recover unused memory. This causes the application to suspend, which is not practical in time-critical systems. Moreover, it is generally the case that applications use memory in proportion to the amount of work they are doing; as the workload increases, so does the memory usage. In systems that rely on garbage collection, this effect tends to force the system to interrupt processing the application most often when the application is most heavily loaded-precisely when it is least desirable.
Although a great deal of effort is being invested in improving Java's performance, many system architects remain skeptical about Java's suitability for high-volume, heavily-loaded server environments, or environments with critical real-time execution constraints.
- It won't last forever-Today's Java will be the next big legacy problem that the computing world has to face. Even the best technologies eventually become obsolete. Some day Java's successor will appear, and (perhaps) take the world by storm, much as Java has done. To the extent that organizations have planned (or failed to plan) for that day, they will spare themselves (or incur) enormous costs and pain, perhaps even save their businesses. To say this won't happen is to be naive. Consider the mindset of IT managers who made total commitments to large mainframe systems with 3270 terminals. At the time, these managers either completely failed to consider what might happen when these systems became obsolete, or they made naive assumptions about the cost of evolving or replacing the systems. As a consequence, the IT industry faces a continuing crisis of rising maintenance costs, and extremely high costs of integrating legacy systems. This crisis has also given rise to an entire sub-industry of bizarre technology such as screen-scrapers- Rube Goldberg software contraptions to connect to a rigid, un-accommodating technology to which organizations swore eternal allegiance, but now hangs like an albatross around their necks.
You may well point out that these statements apply equally well to CORBA technology. They do, but in a very different sense. Yes, of course, CORBA will eventually be obviated. All things must pass. However, it is open integration technology like CORBA that provides the best defense against system obsolescence. The main reason that software becomes obsolete is not that it "wears out". It fails to adapt to the changing environment around it. It won't integrate with new applications and evolving technology. It fails because more development effort was spent on building the program's internals, and very little was spent on building the program's interfaces to the rest of the world. Historically, the software development processes followed by the IT world view applications as closed systems, large boxes of functionality to be filled with lines of code. Very little thought or effort has been devoted to packaging applications as flexible components that live in the context of larger, changing systems. This is a programming-oriented view of application architecture. By contrast, CORBA offers an integration-oriented point of view, where design efforts focus on the boundaries between elements of the system. The underlying interface technologies (IDL, IIOP, Interface Repository, etc.) are designed to make those boundaries as flexible, adaptive, and programming technology-independent as possible. Interface technologies such as CORBA not only have longer half-lives than programming technologies, they are the best prophylactic against the aging and death of applications due to dependence on obsolete programming technology.
Real-world distributed object computing requires much more than a communication mechanism; it requires infrastructure. Applications need to find objects that are migrating about the network; objects that the applications need may be dormant and require activation; applications need to obtain services based on general property descriptions rather than specific identities; applications need transactional integrity among groups of distributed objects; the software components that constitute a distributed system need to be administered and managed through standard interfaces; the underlying mechanisms that support communication, location, and other basic services must be reliable, able to recover from errors and re-configure themselves as necessary to provide high availability; the list goes on. You get the idea.
These requirements are met by a distributed computing infrastructure, an architecture of underlying mechanisms and basic services that provide a stable, powerful platform upon which applications can be built. The OMG Object Management Architecture (OMA) provides this platform, including the core CORBA ORB specification and a set of object services (called CORBAservices).
The core ORB specification itself does not dictate a specific implementation architecture. It describes an abstract model for ORB semantics and a set of standard interfaces, extensible through a standard Interface Definition Language. ORB implementers are free to construct their ORBs in any way they choose, as long as they support the proper interfaces and semantics. This freedom is extremely important to ORB users. It means:
- ORBs can be tailored to specific run-time environments or unique system requirements. For example, several vendors offer ORBs specialized for embedded real-time requirements, where an ORB designed for workstations in a client-server system would be completely inappropriate. Though ORBs may have diverse implementations, they can still inter-operate, and applications will still be ported among them. In contrast, RMI is, in essence, a single, specific implementation architecture. If its one-size-fits-all approach doesn't work for you, or your requirements are evolving in ways you might not be able to predict, you're out of luck.
- ORB implementations can evolve rapidly to offer increased performance, reliability, and scaleability without breaking applications. For example, many ORB vendors have begun to integrate their products with high-performance, highly-reliable middleware messaging systems. These ORBs offer builders of large enterprise systems very high quality-of-service communication, with logging, persistent queuing, and so on. Because CORBA is an interface specification and not a concrete code base, ORBs are free to evolve in this way.
CORBA ORBs have been subjected to strong evolutionary pressures for several years now. A diverse, flexible range of products has emerged, ranging from small-footprint "ORBlets" for widely distributed web-based clients, to industrial-strength ORBs suitable for high volume, mission-critical transactional systems. In comparison, RMI, while quite useful, can best be described as a lightweight mechanism suited for a narrower range of tasks.
The OMA also includes a comprehensive set of object services, designed to provide application builders with a foundation of commonly-required capabilities. CORBAservices includes specifications for Naming, Life Cycle, Trader, Relationships, Transactions, Security, and Query, to name a few (there are a total of 13 services at present). These services are essential to real-world distributed object applications.
The builders of Java are also creating services for use with RMI, including a naming and directory service and a security service, among others. So far, these services are not as complete or mature as CORBAservices, and there is a much smaller set of them. Interestingly enough, JavaSoft has adopted the OMG Object Transaction Service (OTS) as the basis for the Java Transaction Service, JTS. We hope this is the beginning of a trend. In the OMG's CORBAservices, the Java community has an opportunity to leverage existing technology without compromising usability or functionality. These wheels don't need re-inventing.
Where do we go from here?
The OMG has moved rapidly to incorporate support for Java into its architecture. In addition to specifying a standard language mapping from IDL to Java, the OMG is developing specifications for automatically generating IDL from Java interfaces. The OMG is in the process of extending the CORBA specification to support passing objects by value, similar to the Java RMI mechanism for passing objects by value. There is also keen interest in the OMG community in adopting a component model consistent and inter-operable with the JavaBeans component model. All of these efforts constitute a recognition of the value that Java technology brings to the CORBA environment. In turn, CORBA has great value to offer to the Java world-primarily, an open standard integration model and direct interoperability with CORBA based on the IIOP protocol. Many visionaries in the distributed object community have suggested that Java RMI can and should be implemented on top of IIOP without any loss of Java transparency or efficiency. On the contrary, the result for Java would be the great gain of transparent interoperability with the most powerful, widely adopted distributed computing infrastructure existing today.
The OMG membership recognize the importance of Java as a programming platform for distributed object technology, and work proceeds apace to merge the two technologies (Java and CORBA) to produce a combined capability whose whole is more powerful than the sum of its parts. The decision by JavaSoft to adopt the CORBA OTS as the basis for JTS is an indication of similar intent on their part. We hope to continue to build consensus and synergy between the two complementary communities and their complementary technologies.