Language Neutrality and the Java Platform |
May 25, 2002 - Nik Boyd |
Through web links, I recently found the ObjectWatch Newsletter from Roger Sessions dated June 5, 2001, which includes an article titled: Is Java Language Neutral? This article raised several questions for me, including the following. What constitutes language neutrality? What criteria should we use to judge the neutrality of a platform? Does it necessarily include complete language interoperability, or merely the ability to develop and integrate components written in multiple programming languages? Even if certain kinds of language interoperability can be achieved, what benefits does such interoperability confer? What are the natural limits of such interoperability?
I will dispute (or at least quibble with) several points made in the ObjectWatch article. While I think it's fairly obvious that the Java platform was not originally intended to support languages other than Java, it clearly has the ingredients needed to support a broad variety of programming languages. The ObjectWatch assessment itself references a list of programming languages for the Java virtual machine and uses this list as fodder for its analysis. But, the ObjectWatch article defines language neutrality in rather narrow terms. Some of the analysis is arguable, or merely shallow, and appears biased upon probing. Some of the analysis seems subtly oriented toward the exclusion of the Java platform in favor of the .NET platform. In contrast, my biases and true colors are obvious. I'm an unabashed admirer of both Smalltalk and Java, as will become apparent if it's not already so.
I designed the Bistro programming language specifically to integrate the best features of Smalltalk and Java, and provide nearly seamless integration between Bistro (Smalltalk) and Java. I could not have done this without the minimum features needed to support the essentials of Smalltalk. The admitted focus of the ObjectWatch language evaluation was "Possibly Commercial Languages (non-Java) that compile into JBC". Now, I will be the first to admit that Bistro is not (as yet) a language that has seen commercial usage. However, I'd like to believe that it has the potential for such, especially after a facility for round-trip conversions between Smalltalk and Bistro has been developed.
In the ObjectWatch article, Bistro was pegged as not emitting Java bytecode (JBC). Actually, the Bistro compiler does emit JBC as a result. It also translates Bistro source into Java source, but it would be far less useful if it did not then compile the generated Java source into bytecode. The development of the Bistro compiler was simplified by doing source-to-source translation and reusing the existing Java compiler. This approach also keeps Bistro at least somewhat platform neutral. For example, in principle, it would be relatively straightforward to translate Bistro source into C# source. Although, if I chose to target C#, the primitive method syntax would have to change to support C# instead of Java.
But, enough quibbling. Let's focus on the features needed to support language neutrality. Let's consider the minimum features that the ObjectWatch article listed and how Bistro addresses each.
The Bistro compiler generates Java source code, which is then compiled into Java .class files (which contain JBC). Also, the Bistro compiler translates (maps) the (Smalltalk) binary and keyword method names into Java method names. Thereby, Bistro classes may invoke methods in Java classes and Java classes may invoke methods in Bistro classes. Bistro also supports dynamic method resolution using the Java reflection facility for those Bistro (Smalltalk) objects whose types cannot be determined at compile time.
Bistro maps the Smalltalk class model onto the Java class model. Because Bistro maps its classes onto Java classes and maps its method names to Java method names, Bistro supports cross-language polymorphic method resolution. However, like Smalltalk, Bistro provides first-class metaclasses, which are mapped onto Java nested classes. Thus, Bistro metaclasses also have polymorphic methods (unlike Java). Although, the metaclasses are optional in Bistro (unlike Smalltalk).
So, while in principle, Bistro base classes can be subclassed by Java classes and vice-versa, this will seldom make sense from a design standpoint. It will certainly make sense to derive some Bistro classes from Java base classes. In fact, this is exactly how Bistro supports the creation of servlets and applets. However, it will seldom make sense to derive Java classes from Bistro classes because the Bistro (Smalltalk) class model is richer than that of Java. Although, this too can be done if the (especially perverse) Java developer understands how Bistro classes map onto Java classes.
Again, because Bistro classes and types are translated into Java classes and interfaces, these abstractions (types) may be freely exchanged between methods in the two languages. Like Smalltalk, all Bistro data types are objects, e.g., Boolean, SmallInteger, LargeInteger, Float, etc. So, primitive Java data types (boolean, byte, short, int, long, etc.) must be wrapped and unwrapped using a compatible object during cross-language data exchanges. The Bistro class library provides methods that support this wrapping and unwrapping. However, the use of these methods is left to the application developer because the appropriate conversions are almost always application-specific (i.e., design-specific).
The Smalltalk exception mechanism is richer than that of Java. Smalltalk provides an exception mechanism that is not necessarily strictly stack oriented (like that of Java, C++, etc.). Smalltalk allows fine-grained control over whether, when, and how the stack is unwound during exception handling. For this reason, Bistro supports both kinds of exception mechanisms. Bistro does not attempt to translate Java exceptions into Smalltalk exceptions and vice-versa. This would not be appropriate because of the differences in the standard exception classes and the differences in the exception models. However, Bistro does support both exception models. So, if an application has a need to perform such translation, it can be done. For example, a Bistro application could catch a Java exception and then signal a Smalltalk exception.
The Bistro class library implements the standard Smalltalk interfaces, those type and method signatures defined in the ANSI Smalltalk standard. The Bistro class library is implemented using the Java class library. For example, many of the Bistro (Smalltalk) Collection classes wrap the corresponding Java Collection classes. The standard Smalltalk Streams are likewise implemented using Java Streams. This implementation approach maximizes reuse of the existing Java platform services and supports the potential for interoperability between Bistro (Smalltalk) and Java classes that might need to share collections and streams. However, upon reflection, it seems to me that the need to share instances of these utility classes between Smalltalk and Java applications will likely be rare.
So, what can we conclude from this counter-assessment? Some of the evaluation criteria listed in the ObjectWatch article raise important questions about design intent and expression. Should a language neutral platform impose interoperability on the type systems of the supported programming languages, and if so to what degree? Should language neutrality include cross-language exception handling? What are the minimal features truly required to support maximal interoperability without imposing artificial limitations on the supported languages? Some of the minimum features the ObjectWatch article listed are a bit overstated. The article concludes that:
"None of the non-Java JBC emitting languages indicate that they can support the minimum features that I previously identified as necessary for true language neutrality. None, for example, seem to support either cross-language polymorphic method resolution or cross-language exception handling, features that are absolutely critical for true language neutrality."
However, not all programming languages have classes with polymorphic methods. Those that don't clearly have no need for "cross-language polymorphic method resolution." It just so happens that Bistro does, and the Java platform supports this adequately. Also, very few programming languages share a common exception model, but blaming a platform for these disparities in language models seems extremely obtuse to me. The ObjectWatch assessment misses an essential point - some programming languages are richer and more expressive in certain areas than others (e.g., Bistro vs. Java). Rich programming languages express certain computational ideas more efficiently and succinctly. This is why such differences exist.
A programming language that supports a richer programming model can often be mapped onto a simpler one if the simpler one has the requisite capabilities to support such a mapping, as Java has for Bistro. However, where a direct mapping would impose unnatural limitations on the richer of the two, it may make sense to expose the limitations of the underlying one, but it does not make sense to shackle the richer language with those limitations simply to achieve some pathological level of interoperability. Quite the contrary, it makes sense to elevate the underlying platform with the additional capabilities of the superior language, and then provide mechanisms for interfacing with and reusing components developed in that language.
In contrast to the criteria suggested by ObjectWatch, I suggest that the following are the minimum (necessary and sufficient) platform features required to support language neutrality:
However, I do not mean to indicate that all supported programming languages should be required to use these features. All the features listed by ObjectWatch can be implemented with these four features, but not all programming languages will use all of these features. Of course, the unused features will impose limitations on the level of language interoperability achievable. But, that may be a natural consequence of disparities between programming language models.
Comprehensive, seamless, cross-language interoperability is an oxymoron.
Requiring this capability of a platform and the languages it supports is unwarranted and untenable. Programming languages should not be forced to a lowest common denominator of conceptual design. If they were, there would be no point in having different programming languages. Some of the interoperability criteria the ObjectWatch article listed simply do not make sense in all cases. Of those that do, some kinds of interoperability may be more difficult to achieve than others with the Java platform. However, the Bistro project demonstrates that they can be achieved where appropriate.
Smalltalk over Java: An Introduction to Bistro - Provides a
comprehensive overview of the Bistro programming language and its relationships
to Smalltalk and Java.
The Bistro Project - Provides access to the open Bistro
source code and notes regarding the ongoing development of Bistro.
The Bistro Papers - Provides access to the research papers
that led to the development of Bistro.
Java is a trademark of Sun Microsystems, Inc.
ObjectWatch is a
registered trademark of ObjectWatch, Inc.