This text was created in response to a question by ObSoft S.A. in France.
Brief comparison of Component Pascal and Java
Cuno Pfister, Oberon microsystems
Component Pascal is to Pascal what Java is to C and C++: a modern and safe next-generation language that combines the flexibility of dynamic languages with the robustness of static languages. Like Java, it builds on decades of experience, and makes reuse of existing skills easy. Like Java, it supports component software much better than its predecessors. Compared to Java, it is easier to learn and allows to produce more efficient code.
The most obvious difference is the "look and feel" of the two languages. Component Pascal is syntactically clearly in the Pascal family, while Java is in the C family. But this is a relatively superficial difference. Concerning the more important "design for safety", Java and Component Pascal are closely related, while C and even original Pascal (e.g., untagged variant records) are comparatively unsafe. Among other things, safety also implies automatic garbage collection. Garbage collection is necessary to avoid memory leaks and, more importantly, dangling pointers. Both Java and Component Pascal support the dynamic loading of code and metaprogramming (reflection). As a result, both languages can use virtually the same run-time system. This is proven by the real-time operating system JBed (http://www.jbed.com/) and a Component Pascal compiler that produces standard Java byte code class files. Note that C or C++ could not be translated into Java byte code, due to their inherent lack of safety. In this fundamental respect, Component Pascal and Java are closer than Java is to C++!
Component Pascal is more efficient than Java. Unlike Java, it also supports static (stack-allocated) data structures and has variable (VAR) parameters (with IN and OUT variants). Depending on the application, this can have a measureable impact on efficiency. For example, consider the Component Pascal method call
font.GetMeasures(ascender, descender, maxWidth)
which returns three values as OUT parameters. In Java, there is no efficient way to express this simple statement. Instead, a Java method could allocate, set up, and return an auxiliary object which contains the three result values. This is usually too heavyweight, since it not only implies heap allocation, but also the introduction of a new class and class file. Another solution would be to provide three different methods, one for every result parameter. This means three method calls instead of only one. Finally, VAR parameters could be emulated using arrays of length 1. Apart from the ugly misuse of arrays, this would imply unnecessary range checks, type checks, and heap allocation of auxiliary objects. Extensive heap allocation is undesirable in particular in real-time systems, because the need for real-time allocation severely restricts the freedom to choose efficient and flexible memory management algorithms. Finally, Component Pascal has more efficiently implementable arrays, which can be important for numerical and other computation-intensive applications.
Java has built-in support for threads. Component Pascal doesn't provide this feature in the language, because it leads to unportable software: Java threads can behave differently on different platforms. Furthermore, the Java thread scheme is too limited for hard real-time software: Java threads only support ten different user-assignable priorities. Hard real-time systems on the other hand require deadline-driven scheduling policies such as Earliest Deadline First scheduling, which dynamically apply a virtually unlimited number of priorities.
Unlike Component Pascal, Java has exception handling support. This works quite well, except for real-time systems. The problem is that Java exceptions are used also for debugging purposes, which in principle has nothing to do with exception handling. Due to this unfortunate mixture, the Java stack must be frozen and copied when an exception occurs, which is expensive and causes unpredictable delays.
Java has another feature which is problematic for real-time systems: its initialization semantics. The initialization of a Java class is delayed until it is used for the first time. This is reasonable for Internet software, since it allows to avoid (down)loading of classes that are never used. For real-time systems, however, this is fatal: an interrupt handler that should respond in 20 microseconds must not cause several milliseconds initialization time just because it is used for the first time... Moreover, implementing lazy initialization is fine for an interpreter, but it forces a compiler to generate suboptimal code.
[ Note that JBed adds a real-time API that overcomes the limitations of the built-in thread mechanism of Java, and it strictly separates exception handling from debugging. As for the initialization problem, it remains to be seen whether Sun can relax the language definition to allow earlier initialization. Lazy initialization is not difficult to implement, but it is never what you want in a real-time system. In spite of this minor ugliness, Java is still a far better language than C++, even for real-time systems.]
Component Pascal adds a few new features (e.g., implement-only export, explicit NEW attribute for newly introduced methods, EMPTY methods, LIMITED records) that specifically help to keep large evolving component-software systems under control, by making refactoring less risky. Basically, Component Pascal allows to better express design patterns explicitly in a framework's interface, so that the compiler can check for consistency of components with their component frameworks. This is crucial for getting closer to the ultimate goal of safe plug & play of independently developed components - in other words: to inexpensive component software.
Probably the most important difference is complexity: the language definition of Java includes over thirty classes with over 300 methods. Moreover, the language features (and sometimes even the standard classes) interlock very tightly, which often makes it difficult to truly understand one feature without already having understood the others. As a result, casual use of Java has proven difficult and more time-consuming than expected. Component Pascal is a much smaller and less complex language than Java. There are two main reasons. First, Component Pascal is, despite its small size, a language that can be understood and used incrementally, by progressively disclosing new features when they are needed. Second, Component Pascal leaves many Java features to libraries. The above mentioned thread and synchronization mechanisms are an example. As a result, further clean layering of mechanisms and abstractions is encouraged, while Java and large parts of the class library seem to form a vast and conceptually flat "web" of concepts.
(c) 1997-1999 Oberon microsystems, Inc.