2.3 Third-generation component models
The complexity of second-generation component models stems partly from their ambition, and partly from the fact that they only introduce new technology on top of traditional technology, making no attempt to redefine the traditional technology and the abstractions that come with it. These component models work with traditional languages, are written for traditional platforms, and provide tools that are mere adjuncts to the tools that come with the platforms they target, such as compilers and linkers. The old technology is left undisturbed—it is simply built on top of. Added to, not changed.
Third-generation component models are radically different in that they no longer target a large number of platforms. They target just one, and one that already provides many of the services associated with second-generation component models, making for conceptually much simpler technology (but no less powerful). Prominent examples of the platforms that third-generation component models are built on top of include Sun’s Java platform, and Microsoft’s .NET platform. Concrete component models that take advantage of these platforms are studied in Chapter 5.
The platforms that third-generation component models are built on have virtual machines at their core. As a result, components written for such a platform run on many different native platforms, but only need to target one virtual platform. As long as a component does not make direct use of the services offered by the native platform, it will run anywhere there is an implementation of the virtual machine. Technologies such as just-in-time compilation (JIT) and ahead-of-time compilation (AOT) help make code written for virtual machines competitive with code compiled for native architectures from a performance point of view.1
There have been proposals suggesting that components should never run in the caller’s operating system process to protect stateful objects instantiated by the component from tampering, using hardware memory protection available in modern architectures (Szyperski et al. 2002:79). Such heavy-handed methods are made obsolete by forcing components to be written for a virtual machine that has no instructions that allow code to access memory directly (or relegates such instructions to an “unsafe” mode that must be specifically enabled).23
Second-generation component models are forced to standardize concepts not directly related to software components, such as memory management. The platforms that third-generation component models build upon have subsumed many of these technologies, making it possible for third-generation component models to focus on enabling software components. This makes it significantly easier to use and understand third-generation component models, as they simply extend the rich functionality of the platforms on which they are built.
These are some of the technologies standardized by second-generation component models that are part of the platforms used by third-generation component models:
Object model. Interfaces, classes and objects are directly supported by the platforms discussed here, and by most of the programming languages that target these machines. Late binding, implementing interfaces, instantiating objects and even extending classes are thus directly supported by the virtual machines. Language-level support for interfaces means that no separate interface description languages are needed; interfaces are simply specified directly in the implementation language.
Runtime metadata. These platforms maintain runtime-accessible metadata on classes, interfaces and other types, making it possible to explore these aspects at runtime. This support makes it easy to support very late binding, and thus scripting languages. Access to type information at runtime also makes it possible to forego the generation of proxy classes at build-time.
Memory management. Third-generation component models rely on the automatic memory management used by their platforms, which is universally garbage collection.
Error handling. Whereas some second-generation component models resort to using the return value of operations for error information, third-generation component models use the exception handling standardized by their platforms.
Naming. The platforms supporting third-generation component models mandate their own naming scheme, which is simply adopted by the component models themselves.
Layering component technology on top of mature environments that already provide support for object-orientation, runtime type information, garbage collection and the like means that component technology can concern itself with only realizing software components, considerably simplifying third-generation component models.
- Just-in-time compilation and ahead-of-time compilation compile the machine instructions for the virtual machine (known as bytecode) to machine instructions for the native processor, essentially treating the bytecode the same way a compiler back-end treats the intermediate language produced by its front-end. Ahead-of-time compilation, also known as “static compilation,” compiles bytecode to native machine code before the program is executed. Just-in-time compilation, also known as “dynamic compilation,” compiles the whole program or parts of it at runtime (parts that are not compiled are interpreted). Just-in-time compilation is interesting in that it can take runtime aspects into account, meaning that the code it generates can, in theory, be better than statically compiled code—eliminating unneeded dynamic dispatch or simplifying complex code that is always used in one specific way, for instance (Stoodley et al. 2007).
- Some instructions may only be safe if used as prescribed. For instance, the Java virtual machine does not allow programs written for it to jump to locations that are outside the currently executing method. A “bytecode verifier” can be used to verify that untrusted code does not flout these rules before it is executed.
- This might be considered a computer application of the Sapir-Whorf hypothesis in linguistics, which postulates that natural language shapes our perception of the world (McGee and Warms 2004). George Orwell used the Sapir-Whorf hypothesis to great effect in his dystopian novel Nineteen Eighty-Four (2003), in which the dictatorship has constructed a new language, Newspeak, which is a variant of English lacking words representing concepts that the regime would prefer the people did not ponder, such as “rebellion” and “freedom.” A virtual machine with no instructions for memory freedom (in the sense of being able to access and write to arbitrary memory addresses) has no means of even expressing this concept.