When James Gosling first developed Java he had a great idea: create a tool that would allow device manufacturers to change their hardware as the technology evolved without having to rewrite the software for each new hardware generation. Hence the Java virtual machine separating the application code from the hardware, and ultimately therefore Java's success in the hand held industry.
There are a billion cell phones out there ratifying this idea - along with his application of core compsci teachings about safe memory usage, object reuse, and language structure.
Great, except that now Java also forms the basis for most larger scale programming projects and has become a kind of jack of all trades for the web - but I don't believe any of those applications fit the operational model built into Java.
So what happened? Microsoft happened: specifically the protection the JVM offers handset manufacturers facing the need to adapt quickly to hardware change applies equally well, if inadvertently, to software developers facing the need to adapt quickly to arbitrary changes in the Microsoft client environment. Basically the JVM was designed to protect software developers from external change - and Gosling was thinking hardware, but it turned out that the JVM does the job for software change too.
And then, Microsoft happened again - this time driving server side Java development in response to its attempt to embrace, extend, and extinguish the windows client JVM. They lost in court over that one, but by then Java developers had moved to perpetuate their investment by running it on servers they could control - and Sun had a run away hit on its hands that was starting to drive software strategies in the data center. Unfortunately the fact that Java is the most effective tool we have for protecting code value against Microsoft doesn't say anything about how good it actually is as a programming language - in fact seeing people using Java on Solaris or any other Unix always reminds me of http://www.bubbygram.com/zenjewishhumor.htm> a sad story about a guy buying a suit:
Izzy goes to a local tailor to have the final fitting on a custom-made suit. Right away, he notices that the right sleeve is too long.
"Ehhh, don't worry about it," says the tailor. "Look, you just hold your arm out in front of you and crook a little like this, and see? It's perfect!"
"Yeah, but the left leg is too long," Izzy moaned. It's dragging on the floor. I could trip over it."
"Not to worry. Just bend your knee a little, like this, and it will ride up just enough to cut right at the ankle."
"OK, fine," Izzy laments, "but look at the collar! It's way up around my ears."
"That's nothing! Come here. Hunch your shoulders up a little. No, a little more? Now look at yourself in the mirror! Did you see such a well-fitting suit?"
And so, all krinked up, Izzy pays the tailor and, wearing his new suit, limps out of the shop into the street, looking like a pretzel. He nearly runs into two old ladies.
"That poor man!" whispers one to the other.
"Yeah," says the other, "but what a magnificently well fitted suit!"
That's general purpose Java: a 105MM howitzer if you happen to be hunting rabbits, but a 0.22 if you're going after bear.
There's another side to this too: many of the features that make Java such a good fit for use in devices like cell phones have applicability to general purpose software only because a lot of the software surrounding those uses is inadequate.
For example, garbage collection and strong typing combine as important contributors to Java's status as a "safe" programming language, and both are wholly appropriate to both Java's intended function and to its use within Windows clients - but are unnecessary from both programming and run-time perspectives in the context of business or research applications running under Unix.
Similarly its embedded object model is of tremendous value to developers working in the context of a multi-function application subject to both frequent change and a single JVM run-time environment - but just adds overheads to both coding and run-time efforts when applied to well designed business applications running against relational databases under Unix.
In other words, the things that make Java great for cell phones, TV set top boxes, and Windows clients are the things that protect application integrity during run-time, protect the developer from external change, and allow the code to run in multiple environments - but those same solutions just become overheads when Java is used in environments where the problems it addresses don't occur.
Applications written in K&R C for a Vax running BSD 4.3 in 1984 compile and run under Sun Studio 11 and Solaris 10 today - unchanged. The FrameMaker and Visual Thought binaries I licensed for use under Solaris 2.5.1 in 1994 run unchanged on Solaris 10 today - 13 years, a major OS re-invention, and three hardware generations later. Would Java have helped? No.
This problem is actually worse when viewed from a developer perspective: hire a new developer into an existing Java shop, and you can expect that person to produce negative returns for many months - because it takes that long to learn what's already been tested locally and anything the new employee works on in the interim will actually reduce the productivity of his peers. Starting a Java project is, in other words, tantamount to betting that your entire team will work, unchanged, through to at least the first significant "maintenance" revisions - and that's a losing bet for projects of any scale; unless, of course you're a manager whose goal is to grow his budget rather than produce a product: then Java's popularity makes it a sure winner.