A Comparison of Three Network Programming Environments:
Java, ActiveX, and Inferno
by
Andrew Smith
May 19, 1997

Introduction

    The Java programming language platform has lately attracted much media attention as a new and better language, especially for creating network/internet applications. Java was created by Sun Microsystems and is most commonly known for its ability to add executable content to the World Wide Web by allowing transparently downloadable, small applications called "applets" to be run inside a web browser; these applets make web pages "come alive" with animation and graphics, and this transformed the web from a passive environment for downloading and reading static pages of hypertext, to an active and dynamic environment where a user can interact rather than simply passively view. Java was revolutionary in being the first such system to provide this important new capability.

    Since Java's inception, however, there have been other systems released which provide similar functionality, and among these Microsoft's ActiveX and Lucent Technology's Inferno are most noteworthy. At a high level, all three of these systems can be seen as having the goal of simplifying the creation of distributed, multiplatform network/internet applications and allowing executable content on the web. However, they naturally differ in the particular details of how they achieve this goal and the extent to which they achieve it. The purpose of this paper is to compare and contrast these three network programming environments and is organized as follows. The following three sections will give overviews of Java, ActiveX, and Inferno, describing what they are trying to achieve and their key features and functionality. The next section will then compare and contrast (where this is possible --- some parts of these systems have no counterparts in the others) these three network programming environments based on several important criteria for effective network programming. Finally, the last section will conclude the paper by speculating on the future of these three systems, including whether one of them will clearly dominate the others or whether they will each have their own niche and can be complementary.

Java

    The Java platform is a software platform for delivering and running highly interactive, dynamic, and secure programs on networked computer systems. The core of the Java platform is the Java language; i.e., Java is first and foremost a programming language. One uses Java by obtaining a Java development kit, which consists of a compiler, debugger, standard libraries for I/O, windowing, etc., and runtime system (interpreter --- called the "Java Virtual Machine" by Sun), and creating interpretable programs by compiling source programs written in the Java language. Sun provides Java development kits for Solaris, Microsoft Windows 32/95/NT, and Macintosh; there are also ports of Sun's development kits, as well as separately developed development kits, available for most other popular systems. In addition, to support Java applets, Java interpreters are built into most popular web browsers (Netscape Navigator, Microsoft Internet Explorer, and Sun's HotJava in particular).

    It should be noted that while Java is first a programming language, later additions to the Java platform add important networking functionality and are necessary to consider in performing a fair comparison of Java with ActiveX and Inferno. These additions include JavaOS (a network operating system written in Java), Remote Method Invocation (basically remote procedure calls for Java, allowing methods and data of Java objects in separate Java interpreters, possibly running on separate machines, to be accessed), and JavaBeans (a component object model, defining a portable, platform-neutral set of APIs for software components to talk to each other, thus enabling better software reuse). These additions and others will be discussed further below in the section which compares and contrasts Java, ActiveX, and Inferno.

    Java started out as part of a larger project to develop software for consumer electronics, and this project originally planned to use C++ for development. However, many problems with C++ were encountered which were best solved by changing the language. Thus, part of the project became an effort to clean up and simplify C++. At a higher-level, this effort was one of stepping back to survey modern programming methodologies in order to determine which programming language features are useful and successful and which are not. In other words, Java was designed to use well-understood, useful features from other languages and to solve some of their problems without becoming too complex or losing programming power; at the same time, however, Java's syntax and semantics were kept as close as possible to C/C++ (which are the most commonly used software development languages today) so that Java would be familiar and relatively easy to learn for most programmers.

    Thus, one way to view the Java language is as a cleaned up and simplified, yet still powerful, version of C++ which also includes useful and well-proven features from other languages. Some features were eliminated from C++ because they were rarely used, or poorly understood and confusing (automatic type conversion, templates, operator overloading, and multiple inheritance --- Java does have multiple interface inheritance, however). Other features were eliminated because they can make code difficult to understand and reason about and are not needed in Java (goto statements, typedefs, preprocessors, and global variables). Still other features were eliminated because they were not consistent with or were subsumed by the object-oriented features of Java (structures, unions, and enums, and stand-alone functions). Finally, pointer arithmetic was eliminated because it is notorious as the source of many difficult-to-find bugs in C++, such as dangling pointers, and the use of uninitialized memory; also, pointer arithmetic has been a main source of security problems in C/C++ (i.e., allowing access to memory which shouldn't be accessible), so removing pointer arithmetic eliminates this source of problems.

    In addition, several features were added to C++ in creating Java. These include strict adherence to using classes and the object oriented programming style (users weren't required to do this in C++; also, unlike C++, private and protected access modifiers are strongly enforced in Java), language support for multithreading (multithreading was difficult in C++ because the programmer was required to handle complicated memory management and synchronization manually --- Java handles this automatically), and automatic management of dynamic memory through garbage collection (in C++ programmers must manage memory manually with malloc and free, which can be very difficult to do correctly and leads to "memory leak" errors which are extremely hard to track down). Also, Java adds strict exception handling (handling exceptions in C++ is optional, but is required in Java), array-bounds checking (to eliminate another common source of programmer errors and security problems), and strong type-checking (to aid the programmer in eliminating all bugs at compile time, where it is easier to find them).

    The features described above can be seen as contributing to the success of Java strictly as a programming language. In other words, Java is a general purpose programming language and, regardless of whether it is used for networked or non-networked applications, these features make Java easier to understand and work with, and lead to more robust and reliable software and better programmer productivity 1 . In addition, while these features also contribute to Java's success as a network programming language, there are other features which are more directly beneficial for this purpose: Java is architecture neutral, data portable, highly secure for network applications, can dynamically load code over networks, and has an extensive set of portable APIs for such things as windowing, GUIs, network connectivity, useful utilities such as hash tables, etc.

    Architecture neutrality and data portability are really crucial breakthroughs of Java for network programming and are summed up by Sun's trademarked phrase "write once, run anywhere." An excerpt from the Java Language White Paper concisely describes this:

"Java is designed to support applications that will be deployed into heterogeneous network environments. In such environments, applications must be capable of executing on a variety of hardware architectures. Within this variety of hardware platforms, applications must execute atop a variety of operating systems and inter operate with multiple programming language interfaces. To accommodate the diversity of operating environments, the Java compiler generates bytecodes-an architecture neutral intermediate format designed to transport code efficiently to multiple hardware and software platforms. The interpreted nature of Java solves both the binary distribution problem and the version problem; the same Java language byte codes will run on any platform.....Architecture neutrality is just one part of a truly portable system. Java takes portability a stage further by being strict in its definition of the basic language. Java puts a stake in the ground and specifies the sizes of its basic data types and the behavior of its arithmetic operators. Your programs are the same on every platform-there are no data type incompatibilities across hardware and software architectures."

Another key feature of Java is that code is dynamically loaded at runtime as needed, possibly across a network. This means that Java bytecode files can be very small and thus efficiently loaded over networks. The most visible use of this feature is applets being dynamically loaded over networks to be run in web browsers, but any bytecode file which an applet needs but is not present on the hosting system is also subsequently loaded dynamically.

    Since Java allows executable content (applets) to be easily downloaded from potentially anywhere on a network, it is important to have security mechanisms to prevent malicious or buggy applets from doing damage to the machines hosting them. Another breakthrough of Java's is its comprehensive security handling mechanisms. Java security for applets (note that there are no security restrictions on Java applications, which are assumed to be local to the hosting machine and thus safe) is handled at four levels. First, the Java language itself is safe; in particular, Java's memory management techniques, lack of pointer arithmetic, and array-bounds checking alone prevent many of the kinds of attacks which are common in C/C++. Second, to ensure that faulty or malicious compilers don't modify Java language safety, all bytecodes executed at runtime are screened before run to ensure they obey Java safety rules. Third, all applets are placed in their own separate namespace and are not allowed to replace built-in system classes with their own classes. Finally, all resource accesses (e.g., to files, network connections, etc.) are checked by a SecurityManager object (which is extensible and can be set to allow or disallow particular resource accesses at a fine-grain level; popular web browsers are conservative and disallow almost all resource accesses, however) before performing them. In addition to these four levels, digital code signing and authentication, which uses encryption technology, is an auxiliary security mechanism which can be used to determine precisely a downloaded applet's origin and whether or not it has been tampered with; applets can then be granted resource access rights according to their origin.

    Finally, Java has an extensive set of portable APIs; this allows a large variety of application types (e.g., graphical, GUI-based, numerical-based, etc.) to be portable across many platforms. For example, Java has an abstract windowing class, an image processing class, an I/O class, a math class, and a utility class with utilities such as hash tables and dictionaries. And, importantly, since Java is a language for network programming, it has portable networking classes with many routines for both low-level and high-level network operations. For example, there are classes for both UDP and TCP sockets; these can be used to create distributed client/server applications. In addition, there are also routines for handling protocols like HTTP and FTP, and the URL class allows objects (such as HTML files) to be easily accessed and loaded across the network.

ActiveX

    The basis of the ActiveX technology goes back to the late 1980s and has gone through several confusing name changes by Microsoft marketing since then. Microsoft was late to realize fully the potential of the internet and world wide web, and ActiveX is essentially Microsoft's challenge to Java. ActiveX is currently limited to the Windows 95/NT platforms because it directly runs native Intel x86 executables, rather than interpreting some kind of higher-level, portable bytecode format. Microsoft claims that it is an open solution, however, since they have contracted with several other companies to produce Apple Macintosh and UNIX versions of the technology. In addition, support for ActiveX controls (described below) as downloadable executable content is supported by only Microsoft Internet Explorer, with a plug-in available for Netscape Navigator.

    ActiveX is based on two other Microsoft technologies which are used to simplify the creation of and enhance the capabilities of Windows 95/NT desktop applications: the Component Object Model ("COM") and Object Linking and Embedding ("OLE"). Microsoft had a vision of "document-centric" computing, which would allow users to focus on manipulating and viewing their data as a whole rather than on the different applications used to manipulate and view separate data types. In order to make this vision a reality, Microsoft created the OLE technology which facilitates the creation of "compound documents." Basically, compound documents are simply data files that were created by either linking data files together (the "linking" part of OLE --- thus changing the data in the linked files will change the compound document) or completely copying the contents of one data file into another (the "embedding" part of OLE --- thus changing the data in the embedded file will have no effect on the compound document). "Object Linking and Embedding" is thus a concise way of stating OLE's capabilities.The important point is that, when viewed, a compound document appears visually unified to a user; each linked or embedded data file appears in a separate part of the window onscreen based on the type of data it represents. Thus, for example, a compound document which consists of a spreadsheet file embedded within a word processing file would appear as a single window with word processing portions and spreadsheet portions.

    The first version of OLE simply allowed the viewing of compound documents as a unified whole. To modify linked or embedded files, it was necessary for the user to quit the current application and switch to the application which created that file. This was cumbersome and it would have been nice simply to click on the part of the screen containing the linked or embedded data. Microsoft called this capability "in-place activation" and it was provided by the second version of OLE, which used COM.

    COM was originally created specifically to allow in-place activation. COM is a framework for creating "software components," which are pieces of independently invokable software that are smaller than an entire application. COM is an object-oriented protocol for binary executables (which can be created in any COM-compliant language and compiler,with C++ and Visual Basic 5.0 being the most common) which specifies a standard way for the data and methods of instantiated COM objects to be accessed at runtime; it is abstract enough to allow components (objects) of a compound document to be created independently and to find out about their neighbors at runtime, but also concrete enough to let the components share screen space and file access. COM can thus be seen as providing a robust mechanism for code reuse, which goes beyond source code reuse and libraries and is not tied down to any single language. In essence, OLE 2 used COM to manage and talk to objects in a compound document. A compound document in OLE 2 stored not just data, but also a note of the executable that can manipulate it; this information is stored in a standard form which allows other COM software to read, understand, and invoke it.

    COM is also useful in a more general context than compound documents; in general, it allows Windows applications to talk to other applications and objects on the same machine (for example, an Excel spreadsheet program based on COM could have its functions used by other programs, and not just by end users) and one way to think of COM is as "inter-process communication for Windows objects." Windows 95 also introduced a new standard called OCX, which stands for "OLE Custom eXtension." An OCX is a piece of code based on COM, usually smaller than an entire application program but able to contain its own user interface. The idea behind OCX is that anyone with minimal programming skills should be able to combine several OCXs (called OCX controls) together to form customized applications. In 1995 Microsoft announced that OLE and COM were its new strategy for all its software.

    Microsoft's internet strategy, announced in 1996, was to use their core desktop application technologies, COM and OLE, for the purposes of networking and the internet; this is the basis of ActiveX. ActiveX is Microsoft's name for its computing technologies that 1) add executable content to web pages, 2) allow compound documents to invoke viewing software for themselves, 3) provide a standard mechanism for downloading, caching, and running arbitrary files (whether local or remote). The ActiveX relationship with COM and OLE is that COM components are the most common format to be downloaded and that almost all of those components support Windows OLE interfaces. The basic element of ActiveX technology is the ActiveX control (this corresponds to an applet in Java), which is essentially a simplified version of an OCX control (ActiveX controls aren't required to support their own user interfaces like OCX controls; OCX controls can thus be used as ActiveX controls, but not vice-versa) with network/internet support added. Since COM was a single-desktop solution, Microsoft had to extend it to allow network/internet support. Microsoft thus created Distributed COM ("DCOM"), which allows both local and remote objects and applications to be accessed in the same way; DCOM uses remote procedure calls, as well as a system registry on the local machine containing information about distributed objects, to create this illusion. Finally, for security ActiveX uses only digital code signing and authentication; it would be difficult for ActiveX to supply the extra kinds of security mechanisms that Java provides, since ActiveX directly uses Intel x86 executables and is essentially a scaled-up version of single-desktop technology (which had limited security mechanisms to begin with).

    Microsoft's internet strategy has two important ramifications. First, network/internet-aware applications with functionality similar to Java applications and applets can be created in a way very similar to the way standard Windows 95/NT desktop applications are created; this makes it easier for developers to create network/internet-aware applications, because they can use skills they already know. Second, Windows 95/NT desktop applications, which are based on standard COM and OLE, can be easily modified to become network/internet-aware with ActiveX; for example, a version of Microsoft Word which can load and store files across the machines of a network can be created with small modifications to the desktop-only version. Microsoft's vision is thus that any application should be able to access and take advantage of the network/internet easily and in a standard, unconfusing way for users; moreover, the creation of such applications should be speeded by the programming similarities between COM/OLE and ActiveX and the code reuse benefits of COM. Thus, the distinction between desktop-only software and network/internet software (such as web browsers) is blurred; the user thus sees the same desktop as before, but with network/internet access capabilities cleanly blended in, and doesn't have to learn difficult new techniques for dealing with non-local data.

Inferno

    Compared to Java and ActiveX, Inferno is the most comprehensive attempt at creating an environment for network programming and computing. While Java and ActiveX originated in projects and technology not directly focused on network/internet computing, this was Inferno's focus right from the start. Inferno is primarily a network operating system which is designed to be portable across a wide variety of platforms and devices, and to support distributed applications in heterogeneous network environments. Inferno also has 3 other key components: the Styx communication protocols, the Limbo programming language, and the Dis virtual machine; all parts of Inferno are tightly integrated and were designed from the start specifically to work well together. In addition, software developed with other programming languages, such as Java, C, and C++, will also supported by Inferno (only Limbo is supported at present). Inferno was developed by the same lab and people that produced the Unix operating system and C programming language; there are thus similarities between Inferno and Unix, and between Limbo and C. Although Lucent claims that Inferno is complementary to Java, it is clear that in many ways it is a direct competitor (one of Inferno's creators, Dennis Ritchie, has been quoted as saying that "Java does not go far enough.").

    The Inferno operating system can currently run stand-alone on devices which use Hitachi SH3, DEC StrongArm, Intel Architecture, MIPS, Motorola 68030, Power PC, SPARC and ARM processors. Inferno is unique in that it can provide basic operating system services in an extremely small amount of memory (less than 1 MB), thus making it suitable for almost any kind of electronic device: network terminals, television sets, settop boxes, coffee makers, etc. In addition, Inferno can also run as a hosted, virtual operating system on top of Sun Solaris, Silicon Graphics IRIX, DEC Alpha, HP-UX, and Microsoft Windows 95/NT.

    Inferno's design is based on three basic principles. First, the Styx protocol is used for accessing all resources available to an application, including local and remote text and HTML files, local disk drives, remote database servers, etc. The Inferno operating system translates all Styx protocol communications into the appropriate lower-level protocol, such as TCP/IP, PPP, ATM, etc; applications don't explicitly use Styx, however (all resources are accessed as files --- see next principle --- and these accesses are translated to Styx communication operations, which are further translated to lower-level protocol communications for the specific network by the operating system). Second, similar to Unix, all resources are represented as files in a hierarchical filesystem. Thus, the same familiar open, read, write, and close operations are used to access all resources, such as printers, databases, network connections, and remote files; this greatly simplifies application development, since applications have the same consistent view of all resources. The third principle, which stresses an important aspect of the second principle, is that all resources, both local and remote, are represented as files in a hierarchical filesystem. An application thus has a single view of the network, where the network and its resources have essentially been mapped onto a hierarchical filesystem; accessing remote resources is thus procedurally no different than accessing local resources.

    The Inferno kernel is the lowest layer of software in Inferno, and is the foundation of the operating system; it supports networking (which is itself supported by Styx) and application layers which run on top of it. The kernel handles low-level tasks such as security, memory management, process scheduling, resource management, and interfacing to the hardware. Consistent with the design principles, and similar to Unix, all devices are represented as part of the filesystem, where "/" is the root. Another important kernel activity is the creation and maintenance of namespaces. Namespaces provide a view of the network resources to processes, and are organized as part of the filesystem. Processes create namespaces by first mounting resources and then binding them (Limbo provides syntax to do this). In particular, local resources, such as local files, are usually pre-mounted, while remote resources must be explicitly mounted. Mounted resources can then be bound to different namespaces (e.g., a remote file system can be mounted and then bound to the local file system). Finally, part of security handling is done by the kernel, where all remote resource accesses are authenticated using public/private key encryption; this is necessary in order to limit the network resources available to a process. Digital code signing and authentication, similar to that of Java and ActiveX, can also be used at the application level to provide further protection.

    Limbo and Dis in Inferno are analogous to Java and the Java Virtual Machine in the Java platform: Limbo programs are compiled to an architecture-neutral format which Dis interprets (Dis is built directly into the kernel). Limbo is similar to C and Pascal in its syntax and includes all of their basic data types; there are also several higher-level data types such as lists, tuples, strings, dynamic arrays, and simple abstract data types (it is not object-oriented, however). Limbo is data portable, so all of its data types will be the same in all Inferno environments. Limbo programs are built of modules, where each module has an interface declaration part and an implementation part. The declaration part lists the functions and data provided by the module, the datatypes, and constants, while the implementation part implements the declared functions and any other internal functions (Limbo thus supports a simple type of data abstraction, without multiple instances or inheritance); the declaration part can be put in a separate file and performs a role similar to "header files" in C. Modules are accessed dynamically (i.e., to use another module, a module must explicitly execute a "load" statement), and this helps keep compiled Limbo programs small for fast network access as well as adaptability.

    Limbo has a communication mechanism called a channel which processes use for inter-process communication with other local or remote processes. In addition, multitasking is directly supported by Limbo (support for it is built directly into the kernel, for efficiency), where independently scheduled threads of control can be spawned and coordinated with an alt statement (specifically, alt selects a channel if it is ready to communicate and otherwise blocks until it is ready). Limbo is a type-safe programming language, and type checking is done at compile-time and runtime. Pointers are used, but are strongly restricted (e.g., null-pointer and other checks are done at runtime before dereferencing a pointer). Memory management is done automatically in Limbo through garbage collection. Importantly, the garbage collector is built into the Inferno kernel and all memory allocations are tracked by the garbage collector; this allows very quick and efficient freeing of memory (memory is freed as soon as it becomes unused, without any delay). Like Java, Inferno has an extensive standard API, guaranteed to be available on all Inferno platforms, which contains functionality for graphics, windowing and GUIs, math, string manipulations, etc. There is nothing directly analogous in Inferno to a Java applet or ActiveX control, and there are no web browsers which can download and execute Limbo programs; the equivalent functionality (and more) is clearly possible, however.

A Critical Review: Comparing and Contrasting the Three Systems

    With this overview of the three systems in mind, it is now possible to examine the systems' relative strengths and weaknesses for effective network programming and computing. Comparisons can be made based on several important criteria. These criteria are code and data portability, performance (execution and network), security, ease of network application development (which includes such points as ease of access to network resources, code reuse support, language features and ease of programming for programmer productivity), ability to interact with other distributed system technology, and established market base.

Code and Data Portability

    Code portability means that the same program can be run on many different machine types, without any modifications to the program. There are two types of code portability: source portability (the same source code will run unmodified, but must be separately compiled for each machine type) and binary portability (the same compiled binary executable can be run on all the machine types without modification). Data portability means that the format of all datatypes will be the same on all machine types (e.g., no size or endian differences); data portability is important for correct communication of data in distributed applications spread across a heterogeneous network.

    On this criteria, Java and Inferno are clearly superior to ActiveX. In fact, since ActiveX isn't tied to any specific language it might seem difficult to draw this conclusion. The important point is that, no matter which language is used to create ActiveX applications, only native Intel x86 executables can be created and these can only be used on networks of Windows 95/NT PCs. Microsoft says that they are working with other companies to port ActiveX to Macintosh and Unix, but it is not clear when these ports will be available, how effective a solution they will be, and what the level of code and data portability will be (e.g., source or binary portability?). For the present and near future, it is clear that ActiveX applications are restricted to run only on Windows 95/NT machines and networks.

    Both Java and Inferno, by design, feature complete binary code and data portability and this is a crucial breakthrough of these two systems. They both achieve this level of portability by being firm and clear in defining datatypes and by compiling to an architecture-neutral bytecode format which is interpreted by a virtual machine specific to each type of supported machine. The format of the bytecodes is close to most current computers' instruction sets, so interpreters for most machines can be built without much difficulty. In practice, Java is not 100% portable (e.g., some windowing features are not portable) and Inferno's true level of portability is not clear (it was released much later than Java and is thus not as tested). Nevertheless, the important point is that they are portable by design, and any portability problems will eventually be fixed.

    One might ask whether the issue of code and data portability really matters for ActiveX, since Windows/Intel PCs comprise roughly 90% of the installed computer base. I believe that it does matter for three important reasons. First, ideally consumers should be able to choose the computer system that they want, without being penalized in terms of compatibility and lack of available software; they should not be forced into owning the only computer system that supports the most prevalent standards, protocols, and software --- this is what ActiveX forces on consumers, while Java and Inferno allow freedom of choice. Second, Java and Inferno go beyond the desktop computer market and are flexible for use in future devices and systems; the vision (and likely the future reality) of Java and Inferno is that they support code and data portability for all kinds of desktop computers and many kinds of current and future electronic devices (such as settop boxes, thin client network computers, or anything else with an embedded controller) --- they are thus flexible technologies for the present and future. Finally, by simple economies of scale a software developer can maximize his profits by writing software for the most widely available platform; writing in Java or Inferno (Limbo) means "write once, run anywhere" and thus maximizes profits. Java and Inferno are thus flexible technologies and highly beneficial to both software producers and consumers, while ActiveX is inflexible and most beneficial to Microsoft.

    Finally, another important aspect of Inferno's portability is that Inferno is network portable. In other words, by its design, Inferno can run on any existing network (in particular, TCP/IP, PPP, POTS, ISDN, and ATM) and can be easily extended for any other network; Java and ActiveX are limited in this respect (they run on TCP/IP). The reason for this is Inferno's Styx communication protocol, which is a well-placed abstraction layer; Inferno can be ported to different networks simply by implementing Styx for that network. Inferno's network portability is indicative that it is a deeper, more comprehensive solution for network programming than Java or ActiveX.

Performance

    One might get the impression by reading the previous section that software nirvana has been achieved by Java and Inferno. Unfortunately, the benefits of "write once, run anywhere" come at a performance cost. In order to achieve complete portability, Java and Inferno compile to architecture-neutral bytecodes which are interpreted by the machine hosting the Java or Inferno program. The catch is that interpreting code (which is what Java and Inferno do) is much slower than executing native binaries on the raw hardware (which is what ActiveX does). There are estimates that interpreted Java code is 20 to 50 times slower than compiled C code running natively. Thus, in terms of raw execution performance ActiveX is superior to Java and Inferno.

    Practically, however, this is not as much of an advantage for ActiveX as it might seem. First, many distributed, web-based applications are highly interactive; there are many long stretches where the application is waiting for user input --- for these types of applications, the user is the bottleneck and not the speed of the interpreter. Thus, for these applications execution speed is not so important.Second, since the bytecode formats of Java and Inferno are close to most current machines' native instruction sets, it is feasible and efficient to translate bytecodes to native instruction sequences on-the-fly at runtime for better performance. This is called "just-in-time" compilation, and almost all current Java and Inferno (Dis) virtual machines do this. Code generated by just-in-time compilers runs 3 to 5 times slower than native C for Java and 2 to 3 times slower for Inferno (this is Lucent's claim, anyway); as just-in-time compiler technology improves, the execution performance of Java and Inferno (Limbo) will approach that of native C. Also note that the time to perform the just-in-time compilation at runtime might itself be a performance bottleneck; in practice, however, this is not the case since it is mostly a startup cost, where the results can be cached for future use (this especially helps the performance of loops). Both Java's and Inferno's just-in-time compilers are effective; currently, however, it appears that Inferno has the fastest just-in-time compiler technology. It is also important to note that Inferno can support applications with real-time constraints; it does this by having small runtime overheads (garbage collection and multitasking are built into the operating system and are very efficient, more so than in Java), having small memory requirements, and providing high priorities for real-time constraints (8 priority queues, with preemptive scheduling tailored to real-time requirements).

    Another aspect of performance is network performance. These systems are meant for distributed, network/internet applications, which often need to load code and move data a lot over a network. Larger code files will take longer to load over the network, and thus the systems with smaller code size will have better network performance. Both Java and Inferno (Limbo) load code dynamically as needed (they create "thin binaries" as opposed to "fat binaries") and this translates into a small code size and good network performance. For ActiveX, recall that ActiveX controls are essentially simplified OCX controls and thus have a much smaller code size, leading to better network performance. Also recall that OCX controls can be used as ActiveX controls. Microsoft makes the claim that ActiveX controls are a 240 million dollar a year industry, but the basis of this claim is that the vast majority of ActiveX controls are in fact OCX controls (there is not currently much active development of pure ActiveX controls). Thus, while Microsoft's statement is clearly misleading, it also means that the majority of ActiveX controls (which are really OCX controls) will cause applications that use them to suffer relatively poor network performance. It might not seem that network performance is not that important, but users will not usually tolerate a long wait to download an applet or control (they will simply move on to another web page) and this wait time is directly related to network performance. Thus, Java and Inferno are superior to ActiveX in network performance.

Security

    Security is another crucially important criteria for the effectiveness of a network programming system. It is so important because all three of these systems allow executable code from potentially anywhere on the network/internet to run on a user's hosting machine; hosted code might be malicious or buggy and thus cause damage to a users machine and data, or it might steal the user's private data. This was a problem even before Java, ActiveX, and Inferno (e.g., viruses and trojan horse attacks), but the ease and transparency with which executable content can be brought into a user's machine with these three systems makes it a much larger problem.

    On this criteria, Java is superior to both Inferno and ActiveX. The simple answer why is that Java's security features are a superset of ActiveX and Inferno's. I.e., Java supports digital code signing and authentication, just as effectively as ActiveX and Inferno, plus additional security features (i.e., language safety, bytecode verification, separate namespaces, and restricted resource access). Lucent and Microsoft, however, try to argue that security with digital code signing and authentication alone is sufficient, and that Java's extra security features beyond this do not add value. They also try to argue that Java's restricted resource access security is actually a hindrance, because it prevents applets from doing any useful work (since they are disallowed access to practically all resources on the hosting machine). In fact, I believe that Java's extra security features are crucially important for effective security and it is important to clarify the problems with Lucent and Microsoft's arguments to the contrary.

    The problem with security solely by code signing and authentication is that it is ultimately based on trust. It allows you to know the source and integrity (i.e., whether it has been tampered with) of downloaded code, but does not prevent that code from doing malicious things once it starts: once it starts executing the code has complete access to the resources of the machine. Thus, code signing and authentication require you to trust, given information about the source and integrity of downloaded code, that the code will act properly. To be fair, code signing and authentication can be effective in some cases; for example, if an applet or control comes from a well-known and trusted source (e.g., a large company) then it is reasonable to trust it. However, the source for much executable content is much larger than the number of well-known and trusted sources (i.e., potentially anywhere on the internet). Very little is known about most of these sources, but it is still desirable to access their executable content (since the majority will be trustworthy, but you still always have to be wary of the "bad apples."). With security through only code signing and authentication, there is too much risk in this and only code from the small number of well-known and trusted sources can be used. Java, however, can use both code signing and authentication and restricted resource access together for a better, more robust solution: resource access restrictions for well-known, trusted sources can be relaxed (remember that this is controlled through the SecurityManager, which is programmable), while code from unknown sources can still run, but with tight resource access control.

    In practice, there are several glaring examples where ActiveX has been used maliciously (e.g., to power down a user's machine, or steal money from their bank account) and these kinds of attacks can never be completely eliminated by ActiveX's security mechanisms. Several security flaws in Java implementations have been discovered, but they were quickly fixed. It is important that these security flaws were implementation bugs and not inadequacies of the design (it is much easier to fix implementation bugs than fix the high-level system design). Inferno is not as tested as Java and ActiveX, and so it is not known how effective its security is; however, as discussed above, it is susceptible to the same kinds of attacks as ActiveX.

Ease of Network Application Development

    This criteria is directly related to the ease of use of the programming language being used for development, based on its features in general, its features for network programming in particular, and the overall language environment (i.e., operating system, etc.); on this point Java and Inferno's Limbo can be directly compared. Java and Limbo are similar in many respects. They are both portable and machine independent, type-safe, multithreaded, support interpreting or just-in-time compilation, have automatic memory management through garbage collection, and feature dynamic code loading; both languages seem to be equally powerful and expressive in language constructs for these features (although Limbo's implementation of multithreading and garbage collection are more efficient). Both languages come from the C/C++ heritage, but an important difference between them is that Java is object-oriented and Limbo is not. Limbo makes up for this by having a rich set of basic types (lists, dynamic arrays, etc.) and by supporting modules (which supports simple data abstraction); Lucent claims that this is sufficient and avoids the complexities of object-oriented programming.

    It is not clear in practice which of Java and Limbo is the easier language to program with (Limbo is too new, and there isn't yet any data about actual programmer experience with it). However, object-oriented programming has proven to be an effective and efficient programming methodology, even in C++ with all its complexity and problems. Java is object-oriented and, importantly, a visible and important part of the Java project was to build a better, easier to use object-oriented language. In addition, there is early evidence (see footnote 1 above) that Java is easier to use, leads to higher programmer productivity (compared to C/C++), and is "fun" to program in. Thus, although it is difficult to make such a judgment so early, I would say that Java is superior to Limbo as a programming language (Limbo does have better performance, through the Dis interpreter, but this has more to do with the tight integration of Limbo and Dis with the the Inferno kernel than language design issues).

    It is technically not possible to compare Java and Inferno directly to ActiveX based on programming language issues, since ActiveX is language-neutral. Microsoft makes use of this fact in promoting ActiveX; they make claims to the effect "with ActiveX you can use the programming language and skills you know and are most comfortable with, rather than having to take time to learn an entirely new language like Java." There is some truth to this statement, but it is also a bit misleading. Recall that ActiveX is based on the COM and OLE protocols for Windows desktop applications; these were scaled up for network/internet support to create ActiveX. Thus, Windows developers can use their desktop application development skills (i.e., COM and OLE) in developing ActiveX applications, and this smooths the transition to developing network/internet applications. In addition, the COM component protocol for binary objects and applications is powerful and effective, and supports a high degree of code reuse, within the Windows environment only. Thus, Windows developers can leverage their existing skills to create network/internet applications with ActiveX, but it is not a portable solution. Another catch is that C++ is by far the most prevalent language for building ActiveX applications but doing this is a notoriously difficult undertaking. One developer states in a tutorial on building ActiveX controls that "Most people think component software is a good idea. It is easy to obtain impressive results using components. However, only a few people are creating components, because it is just too hard. The fitness gurus on television say, 'No pain, no gain.' My creed is, 'No pain...No siree Bob!' Although I have written ActiveX controls using C++, it isn't much fun." 2  To be fair, this article goes on to discuss creating ActiveX controls with the newly released Visual Basic 5.0 (the first version with this capability); Visual Basic 5.0 does simplify the creation of ActiveX controls, but it is not yet clear how effective it is.

    The second part of Microsoft's effective claim (i.e., that it is a burden to have to learn a new language like Java) is also misleading. As discussed above, Java appears to be a highly productive language and it is intentionally close to C++ to ease programmer transition; in fact, one experienced C++ programmer who switched to Java says "We've found that we can bring competent C++ programmers up to speed in Java in a matter of days, and they achieve a high degree of fluency in a matter of a week or two. Moreover, we've found that many programmers don't want to go back to using C++." 3  An important thing to note in relation to Java and ActiveX is that Java seems to be the perfect language for creating ActiveX controls; this is mainly because an important common aspect of Java and COM is that they are both object-oriented techniques based on multiple interface inheritance. Microsoft regards this as fortuitous (although Sun probably doesn't) and uses this in their implementations of the Java Virtual Machine in Internet Explorer to automatically translate Java applets to ActiveX controls and vice-versa. Microsoft also claims that, since COM is a software component framework and Java is only a language, COM (and thus ActiveX) is more powerful, flexible and supports a higher degree of code reuse than Java. In comparing COM (ActiveX) to just Java as a language, this claim is probably true. However, a fair comparison would pit ActiveX against the newly released JavaBeans software component framework for Java. JavaBeans is directly analogous to ActiveX, and makes it possible to combine components ("beans") into a coherent application using high-level tools such as GUI-builders; it also provides functionality for persistent storage, scripting, event handling, embedding, etc. JavaBeans creates a simple component environment, completely portable across all platforms, which is just as powerful as ActiveX, but much easier to use. Note that Inferno's Limbo doesn't have any kind of software component framework like ActiveX and JavaBeans.

    The particular language/environment features for network access and programming are also very important to consider in comparing Java, ActiveX, and Inferno. Network resource access is an area where Inferno really shines, and its mechanisms for this are significantly different from those of Java and ActiveX. Recall from above that, similar to Unix, all resources in Inferno are represented as files in a hierarchical filesystem, where the same operations are used to access all resources, such as printers, databases, network connections, and remote files. This greatly simplifies application development, since applications have the same consistent view of all resources. In addition, all resources in Inferno, both local and remote, are represented as files in a hierarchical filesystem (called their namespace). An application thus has a single view of the network, where the network and its resources have essentially been mapped onto a hierarchical filesystem; accessing remote resources is thus procedurally no different than accessing local resources. Accesses to remote resources are ultimately handled with remote procedure calls by the Inferno kernel (as in Java's RMI and ActiveX's DCOM), but the application never sees this; it simply accesses everything in the same consistent way (it does have to mount and bind resources, however --- see the above overview of Inferno for details). Finally, namespaces can be passed through the network and thus applications can have the same view of network resources no matter which machine they reside on. Inferno's handling of network resource access tends to blur the distinction between clients and servers.

    Java has portable networking classes for basic network resource access. These have many routines for both low-level and high-level network operations. For example, there are classes for both UDP and TCP sockets which can be used to create distributed client/server applications. In addition, there are also routines for handling protocols like HTTP and FTP, and the URL class allows objects (such as HTML files) to be easily accessed and loaded across the network. These classes are easier to use than network routines in C/Unix, but do not support as many options. What is interesting about network access in Java are the mechanisms added later; these are three APIs which work together: ObjectSerialization, Remote Method Invocation ("RMI"), and JavaSpace. ObjectSerialization allows any Java object to be turned into an array of bytes, which can later be used to reinstantiate the same object (actually, a copy of the object); this is useful for object persistence in files, or in sending objects across a network. RMI is essentially "remote procedure calls for Java." It allows the methods and data of objects in separate virtual machines (possibly running on a separate machine across the network) to be accessed; it works by having a system registry (server) keep information about remote objects, and uses ObjectSerialization to send objects and requests between machines. JavaSpace is the most interesting network access mechanism in Java; it uses RMI and essentially implements a Linda-like tuplespace for Java. Distributed applications can be built easily at a very abstract level with JavaSpace.

    In ActiveX, one can still use low-level WinSock calls, which have always been available in Windows. The main network access mechanism in ActiveX, however, is with DCOM. DCOM is essentially COM extended over networks. Thus, with DCOM ActiveX applications can access remote COM objects the same way they do local ones. DCOM is implemented similar to Java's RMI with system registries and remote procedure calls. It has similar functionality to RMI, but is not as tested and is, like ActiveX, not portable. There is nothing like JavaSpace in ActiveX.

Ability to Interact with Other Distributed System Technology

    This section briefly describes these three systems interoperability with some other important distributed system technology: in particular, CORBA and distributed database access. CORBA --- the Common Object Request Broker Architecture --- is an industry-wide standard that specifies how computers can treat objects available on a server as if they were actually present in a client program, without worrying about sockets, protocols, packets, and so on; it is a language and platform independent model for distributed objects that is similar to and competes with Java's Remote Method Invocation ("RMI") and Microsoft's Distributed COM ("DCOM"). It was created before Java, ActiveX or Inferno, however, and so is being used in applications today; it is thus important to be able to work with it. The basic idea of CORBA is that it consists of many distributed "Object Request Brokers" which allow objects to locate and make method calls to other objects on the network in a language and platform independent way. Both Java and ActiveX have functionality which allows Java and ActiveX applications to use and interoperate with CORBA; CORBA compliance is not mentioned in any of the Inferno literature, however.

    Distributed database access is important because an important part of most practical distributed applications is access to corporate databases (i.e., distributed applications need a way to access the data that they will work with). Most corporate databases today are relational databases which are accessed using the SQL query language. Java, ActiveX, and Inferno all provide functionality for distributed database access. Java provides the Java DataBase Connectivity ("JDBC") library for accessing any ANSI SQL-2 standard database. ActiveX provides COM-based technology called OLE Database ("OLE DB") for accessing SQL relational databases. Finally, Inferno also provides an API for SQL relational database access.

Conclusion

    It is a common maxim in the software industry that the best technology does not necessarily win the largest market share. For example, IBM's OS/2 is commonly thought to be a better operating system than Microsoft Windows, but Windows dominates the market nevertheless. In the software industry, timing is crucial. The company that releases a new software technology first has a distinct advantage; customers will buy their technology and start using it, and software technology released later by other competing companies will have difficulty gaining market share. This is because the customers will have become "locked in" to the original company's software technology; i.e., they will have already learned the original company's technology and integrated it into their business plan, and it will not be cost-effective to move to the competing companies' software, regardless of its technical merits. In addition, the original company can later release other software products and technology, which only work with the originally released software technology, and thus indirectly lock in the customers to these as well. This is one of the basic reasons that Windows, and other Microsoft products, dominate the PC operating system and software market.

    In the context of this paper, the same thing is happening in the new "network computing" market spawned by Java, ActiveX, and Inferno. In particular, Java was released well before either ActiveX or Inferno and, true to the maxim, it is fully enjoying the benefits of this early release. Java is one of the hottest topics in the computer industry today, and many programmers have started developing software in Java. Looking in the computer sections of bookstores, one will find shelves and shelves of books about Java, a few books about ActiveX, and no books about Inferno. Of course, a lot of this has to do with Java's inherent benefits, particularly "write once, run anywhere," and its ability to provide executable content on the web. Nevertheless, ActiveX and Inferno (particularly Inferno) offer many of the same benefits as Java, but do not have nearly the market share or mind share as Java. In fact, most experts would probably rate these three network computing systems on the overall quality of their technology and completeness of their solution in the order Inferno, Java, and then ActiveX (with Inferno and Java being close). Thus, Inferno is the best overall solution, but has the least market share (almost nothing); for the most part this is due to the fact that Inferno was released so long after Java. In addition, there is almost no marketing push by Lucent so Inferno use has remained stagnant.

    Microsoft's ActiveX does have some attractive points, such as good performance, good code reuse, leveraging of existing programmer skills, and nice integration of desktop and network/internet applications; these benefits could make it the best solution for an organization's intranet of PCs (where security and portability are not big issues). Of the three systems considered in this paper, however, it is currently the least attractive solution overall as a (heterogeneous) network computing system. The two main reasons for this are its lack of portability and its insufficient security mechanisms. Nevertheless, it is possible that ActiveX will win the "network computing system wars." This is because Microsoft is the most rich and powerful company in the software business today, with many resources at their disposal to help them lock-in consumers to the ActiveX system. Java is a real threat to Microsoft; its portability and network-centric focus threaten Microsoft's virtual monopoly of PC software and standards. Microsoft's strategy will probably be to try to subvert subtly the portability of Java programs on Windows systems; in other words, they will probably try somehow to modify Java and the Java Virtual Machine for Windows so that Java programs written in Windows will not run on other platforms or Java programs from other platforms will not run in the Windows Java Virtual Machine. Microsoft is technically prohibited from doing this by their licensing agreement with Sun for Java, but Microsoft is rich and resourceful and has usually gotten their way in the past. One way Microsoft is already doing this is by actively promoting the use of ActiveX controls from within Java applets in Windows; such applets will only run on Windows platforms.

    So how will things shape up for these three systems in the future? Will one of these systems dominate, or can they coexist and complement one another? As stated previously, Java and Inferno are highly beneficial to both consumers and producers (except maybe Microsoft) and thus the computer industry has a vested interest in seeing them succeed. Fortunately, Java is not just hype, but is inherently good technology. It also has a lot of momentum and the number of Java tools and programmers, and the general level of support for it, is continually increasing. In all likelihood Java will continue to be the central focus and language for network computing.

    As stated above, however, Inferno is probably the best overall solution and it is desirable that it have some important role in the future of network computing. It seems unlikely that Inferno will win the language battle (Java is a better language and is already too entrenched), but it does have a very good chance to be the network operating system of choice (Inferno's main strength, after all, is as a portable network operating system --- the Inferno operating system could easily run the Java Virtual Machine, and Lucent is working on adding support for this). Inferno can successfully compete on this front because this is its forte, and because Sun has only recently released their own network operating system, JavaOS, which competes with Inferno. The Inferno operating system is probably better technology than JavaOS (it runs in less memory than JavaOS, is network portable, etc.) and Lucent could win the network operating system battle if they really push Inferno. The outcome of this is particularly important, because these network operating systems will be used in thin-client network computers, which comprise a potentially lucrative market.

    As for ActiveX, Microsoft will probably continue to push its use on Windows PCs strongly. Microsoft has a lot of control over Windows independent software providers, and Microsoft will probably strongly urge them to create software using ActiveX (possibly by threatening to withhold the "made for Windows" logo from their software if they don't). ActiveX will probably not have a role in the non-Windows world, however. Even in the Windows world, it is not certain that it will dominate; I have read reports that many Windows software developers are in fact staying away from ActiveX because of its security and portability problems.

Notes

(1) Theoretically, at least; there is some early evidence, however, that programmer productivity is higher with Java as compared to C++ (see chapter 6 of the reference "Not Just Java."

(2) Al Williams, "Visual Basic 5 and ActiveX Controls," Dr. Dobbs Journal, March 1997.

(3) See chapter 6 of the "Not Just Java" reference.

References

1. Van Der Linden, Peter, "Not Just Java," the Sunsoft Press Java Series, 1997

2. Flanagan, David, "Java in a Nutshell," O' Reilly & Associates, 1996.

3. Van Hoff, Arthur, "The Case for Java as a Programming Language," IEEE Spectrum, January/February 1997.

4. Sun Microsystems Whitepaper: "The Java Language: an Overview." Available at http://www.javasoft.com

5. Fritzinger, J. Steven, Mueller, Marianne, "Java Security." Sun Microsystems. Available at http://www.javasoft.com

 

The following Inferno articles were obtained at http://www.lucent.com/inferno

6. Lawton, George, "Lucent Brews Inferno."

7. "Inferno: la Commedia Interattiva."

8. Mohseni, Piroz, "Fanning the NC Flames: Inferno, the Network OS."

9. "Inferno System Specifications."

 

10. Chappell, David, "Understanding ActiveX and OLE," Microsoft Press, 1996.

The following ActiveX articles were obtained at http://www.microsoft.com/activex

11. Cluts, Nancy Winnick, "The Microsoft Active Platform."

12. "ActiveX FAQ."

13. "Activating the Internet with ActiveX Technologies."

14. "Java and ActiveX"