Monday, February 12, 2007

Java, Objects and Static Types

I seem to be on a roll myth busting. This one is prompted by a comment by Peter Kriens, in response to my previous post on Java and component models. The sentences that drew my attention where "interestingly, the type information in the language allows us to provide quite a few guarantees." and "for large systems where you get legacy parts from all over the place there is something to say for type information ..."

Now it would be only fair to allow Peter to explain himself further and not to read to much into what he has said, but his words did bring to mind a common myth, namely that dynamic languages have no type information, and perform no type checking. Well they do!

I'm old enough to remember programming in C, with no stack trace and the dreaded "Segmentation fault - Core dump" Unix message on program failure. C allowed no type information at runtime. You could declare pointers of type (void *), which meant that they could point to anything you liked. You could cast to an assumed type and the language would not check for you - in the end you would try to access a segment of memory not allocated to you by the System and bang!

Here is where my memory gets a bit hazy, but I believe things improved with C++. There was still void* pointers, but I believe C++ introduced a dynamic cast that did some checking at runtime.

So a long intro, but I wanted to get everyone on to the same page. So dynamic languages like Smalltalk do their type checking at runtime. If a type mismatch is detected, the program doesn't go bang like with C, but the language notifies you of the error and will even launch a debugger at the appropriate line of code. So Smalltalk is a strongly typed language, the difference between it and say C++ is that the type checking occurs at runtime not compile time (Smalltalk also gets rid of void* pointers, Java does likewise).

So what are the consequences of these differences?

* Well with Smalltalk, all type mismatch errors can only be detected by running your programming. So no coincidence then that test driven development and SUnit came from the Smalltalk community. With C++ the compiler at compile-time performs checks statically. So some believe that unit testing is less critical (I disagree).

* With Smalltalk, the overhead of dynamic message dispatch and the runtime checks makes the language inherently slow. With C++ there are few runtime checks, all function call indirection is removed at compile time and hard coded into a VTable. This allows for the use of an optimising static compiler, which inherently produces faster runtime code.

* Smalltalk is fully polymorphic at runtime. What this means is that objects can take many forms (implementations) at runtime. So any class of object that satisfies a caller’s request can be substituted in at runtime. This is known as late-binding, and has significant implications. C++ is only partially polymorphic at compile-time, common interfaces must share a common implementation (A common base class or abstract base class). At runtime object type is fixed (hard-coded), so no polymorphism.

So along comes Java. Without justification, I will assert that Sun produced Java in a hurry. Oak was aimed at low powered, low memory home devices, so the static optimising compiler route was the obvious one to take. So Java has inherited many of the properties of C++. Namely, highly performant and static (fixed).

For Objects that come 'alive', you require different properties. Sun did a lot of research in this area. The Self Project determined that Objects needed to poses a number of properties:

* Directness (you manipulate objects directly)
* Uniformity (everything is an object)
* Liveliness (modeless, no run/edit mode, fully dynamic)

These properties are inherent in Smalltalk, and the Self Project hoped to build on them. Self explored a number of important OO concepts that are still relevant today, but the implementation was a memory hog, and you needed a super fast computer to run Self.

Here is a good video on Self.

So the reason for saying all of this is that "compile-time' type safety was always an after thought with Java. The real reason why Java is static is performance. Also from a Marketing point of view the static label was useful, as the bulk of the developer community out there were C++ programmers and comfortable with the static programming approach. To them liveliness meant nothing.

In 1995 some of the original Self team were ready to launch a new Smalltalk implementation known as Strongtalk. The idea was to address what was seen by many as the shortfalls of Smalltalk - slow performance and no compile time type checking. They addressed the performance problem by optimising out dynamic method dispatch at runtime using a dynamic compiller. The approach was similar to that used in the JVM JIT today, but their approach also allowed for de-optimisation on the fly back to interpreted code, allowing them to satisfy the semantics of dynamic dispatch needed for 'liveliness'.

They also looked at the runtime type checking issue. At first they made the same mistake as C++/Oak etc and assumed that compile-time type checking had to do with the runtime implementation. It doesn't. Type declarations in a static language can be thought of as annotations. They annotate the code and tell the compiler how best to optimise method calls. They also allow the compiler to perform checks. What the Strongtalk team did was to delegate the optimising role to a dynamic runtime and retain the static type checking at compile time. To do this they needed to add Type declarations to the Smalltalk source code, this is done by way of annotation. So Strong talk can compile both Type annotated code and un-annotated code. At runtime Strongtalk maintains full dynamic messaging semantics - so you end up with the best of both worlds.

As the startup company who built Strongtalk in secret where about to launch it on the world, Sun came along and bought them up. The Strongtalk developers where moved over to work on Java and the JVM and are responsible for the Java hotspot JIT technology we have today. Type-feedback and Type annotations sat on the shelf for over 10 years.

Fortunately Sun as recently released the Strongtalk code as Open Source:

Strongtalk Home Page

But imagine how things would have been different if they had released Strongtalk as a product in 1995? Or better still if they had ported Java to Strongtalk using Type annotations?

* There would be no OSGi (no need)
* Ruby probably would not have blossomed beyond the Perl community (no need).
* Smalltalk would perhaps still be thriving today.


Sunday, February 11, 2007

Java, Component Models and Class Loader Hell

I've been drawn back to TSS again. There is an interesting thread where Bill Burke from JBoss-Seam goes head to head with Rod Johnson of Spring. Now it doesn't surprise me that Rod Johnson is a bit of an egocentric jerk - I know someone who worked him for years who told me as much. It was interesting though to see the JBoss guys break their usual aloof pseudo-intellectual demean a: read here.

Both of these frameworks claim to provide a component model for Java objects. So the first thing to clear up is what is a component? Well as far as I can tell, a component is a course grained object that can be bound to other coarse grained objects after compile time. So components are an invention for static OO languages, in dynamic OO, all objects are components.

Right with that out the way (anyone who is still not convinced, I would suggest exploring the runtime differences between a virtual function call as used in C++/Java/C# etc and polymorphic message sends as used in Smalltalk, Phython, Ruby etc), here is why do I believe that EJB's are a flawed component model.

Let’s take a simple example. Component A uses Component B. A configures B and registers a number of callbacks with B so that B can notify A. A is packaged in its own EAR (or 'war' or 'ejb-jar') and so is B. So what is the problem?

Well A must have access to the Interface of B, I will call this B' and B must also have access to the callback interface of A, which I will call A'. So there is a mutual dependency between A' and B'. With the J2EE class loader model, each component has it's own class loader (CL). Class loaders are arranged hierarchically. So the CL for B can be a dependent of the CL for A, or visa-versa, but two class loaders cannot be mutually dependent.

So you cannot have A<-->B relationships between J2EE components. Apparently OSGi is meant to be addressing this, but it seems a pretty fundamental language flaw to me. It will be interesting to see how they plan to get over this one!

Oh, yes I forgot Spring. Well IoC is nothing new. It allows you to separate interface from implementation, deferring binding untill runtime (back to message sends versus virtual function calls again). So again, by default all dynamic OO objects have this property. In Java it can be achieved with the use of an Interface and the reflection API, which is effectively what the Spring bean factory does. Fortunately Spring doesn’t go in for this separate class loader nonsense - so no class loader hell here - but if you choose to package your Spring application into a WAR, then you have no runtime binding of components either, so A<-->B, with Spring becomes AB. So if you want to change implementation to A<--->C at deploy time, where C implements B' you can't.

So it turns out that Spring isn't a component model at all - oh dear!

So neither of these so-called "Component frameworks" can do what Smalltalk did out of the box, over 30 years ago. Maybe they should have discussed this poignant fact on TSS, instead of squabbling like school girls.


Sunday, February 04, 2007

Java - State of Denial

I've been participating in an interesting discussion on Tuple Spaces over on TSS

Actually the discussion was on JavaSpaces, but since Tuple Spaces is the "non-branded" name for the architectural pattern - we quickly moved on to Tuple Spaces. There were some useful posts by people knowledgeable in the "distributed" Java technology space - like Cameron Purdy of Tangosol, but the debate quickly deteriorated (IMO) into a discussion of what you should and should not do with a Tuple Space.

To me this seemed very odd, because Tuple Spaces as a concept has very few restrictions, in fact the API is very simple, just four verbs (read, write, notify and take). So why the big discussion about what you can and can't do? Then it dawned on me. Some of us were talking architecture, whilst others where still talking implementation. So what Cameron was perhaps saying was that the Java implementations of Tuple Spaces have various limitations. Given that Java and distribution is Cameron’s area of expertise, he could well be right.

Yet, I know of at least one other implementation, not in Java that isn’t limited in the way he describes. So why would someone with his level of expertise not know of other implementations too?

I think this is a symptom of something I've seen descend over the java community over the years. I think what has gone on with the Bush Administration over Iraq, in some ways resembles what has happened to the Java community:

The first similarity is having all the answers. The JCP was meant to be the answer to everything. By committee Java would flourish and evolve. All good ideas would emanate from the JCP, and we didn't need to look elsewhere - Baker/Hamilton, no thanks!

The second similarity is staying the course. What do you mean that AppServers and EJBs are dead and buried? We intend to stay the course despite the fact that no one is adopting EJB3.0.

The third is denial. Java is still cutting edge, we are leading the vanguard in technology innovation - we will win through!

The Java community has become somewhat inward looking and entrenched IMO. Much of the interesting ideas are coming from outside Java, but the Java community consumed in its own grandeur is blissfully unaware of the rest of the world.

The sad thing is, that even Microsoft is evolving. WPF and WPF/e will deliver on the promise of Applets, which Sun made years ago. In contrast the Java community has stagnated, stuck with a language designed in a hurry to power toasters. Nothing is wrong with that btw, we've all got to start somewhere, the problem is though, that through denial no one sees the need for change.

So C# 3.0 is adopting even more from functional languages, whilst Java's thinks about closures. Ruby comes along and shows what can be done with a dynamic message send, and the Java community, slays the messenger Bruce Tate. The last time I looked Bruce was hiding out on the IBM forums writing articles for people who where interested in "crossing borders" like he had.

So the experts in distributed data solutions in Java haven't heard of Croquet. I guess it is not of interest, even though the Croquet team lead is the guy that invented Objects in the first place!

I don't believe Java is going to go away any time soon, but unless this culture of denial changes I can see it suffering a long lingering death. That in itself is not necessarily a bad thing, times move on. The problem though is that a lot of programmers have identified themselves with "Java". So they are no longer just programmers, they are "Java" Programmers. I once responded to a post that was clearly antagonistic towards Ruby from someone who openly admitted that he had only "read about it". Given his ignorance, I was surprised at his antagonism. When I asked him why, he came out with all the usual static typing arguments, and he also mentioned that he would not go on to a Ruby forum and make comments on Ruby. I guess by implication, he meant that I should not comment on a Java forum because I was obviuosly a Ruby programmer. I guess it never crossed his mind that I may program in both!

I could imagine Rumsfield coming out with a stupid statement like that. So the Java community has become tribal and partisan - and even Microsoft is more open minded and outward looking knowadays (have you noticed that XAML looks a lot like Adobe Flex?).

I guess the final service Java can provide to the developer community is as a repository for developers with a closed mindset. People able to think for themselves can just leave, much like Bruce Tate did, and move on to more interesting things. And the "I've just put the latest JCP acronym on my CV" programmer can stay with Java safely out of everyone’s way!