Summary
Get more bang for your buck with multi-platform application development, but be prepared to work for it, even in Java.
Advertisement
Write once run everywhere has probably been one of the very first phrases we read about Java years ago. I remember being quite excited at the idea of easily writing a bit of code and seeing decent looking GUIs on my Sun Sparc 2. No more Motif, and better yet, I could take that same object code and run it on my 486 desktop PC running Microsoft Windows. Quite exciting. That was the GUI version of a "Hello, world!" test.
Years later I'm managing the Visualization Group here at Tom Sawyer Software. One of the main products we have is called the Graph Editor Toolkit. We support all major frameworks, Java, MFC, and ActiveX. This toolkit helps our customers write applications to more easily and effectively visualize their relational data. We cover most markets, as our graph-based display (with nodes representing the entities, and edges representing relationships) is generic and very extensible.
Thus, this product needs to be highly optimized so it can handle tens of thousands of objects drawn on the screen, and it needs to behave in the same way on all platforms. One can say that slightly different behavior between the Java and MFC or ActiveX versions is acceptable, but what about the same Java product running on Microsoft Windows, Linux, and HP-UX, for example? It turns out this is becoming a more and more challenging task, with different JDKs being released, and different vendors having their own implementations of the Java VM. I'm finding that we need to spend more and more time fine-tuning our highly optimized graphical toolkit. The platform matrix we have to go through looks just as complicated as our non-graphical C++ based products which run on all types of operating systems with various compilers. I almost wish we had #ifdef's available, because right now we have various runtime checks of whether we're running under JDK 1.2, or under HP-UX, or Sun Solaris, etc. Cursors and images behave differently, some mouse events are not properly registered sometimes, and all of these issues must be addressed separately if the Java application is to run consistently and smoothly in every platform that Java supports.
So I guess it's true that there's no such thing as a free lunch, and for sophisticated Java applications, you have to earn your lunch for every platform you support.
At the moment I don't have to deal with the same sort of problems you have with your product because I'm involved in J2EE development where we only have one deployment platform (IBM WebSphere 5 under Linux), but I can sympathise because I have been there in the past.
Do you think, though, that this is down to a weakness in the design and specification of the JVM or some laziness on Sun's part in certifying JVM implementations with the Java label? In other words, are we seeing "sloppily implemented" JVM's or is the JVM spec just too fuzzy on some points?
> Do you think, though, that this is down to a weakness in > the design and specification of the JVM or some laziness > on Sun's part in certifying JVM implementations with > the Java label?
I don't know if you're using JVM as a shorthand for the whole Java spec. Bytecodes, etc. work pretty much the same (modulo JIT/Hotspot bugs). On the other hand, packages relying on OS-specific code can have different behaviors on different platforms.
AWT, as the original article notes, is one of the worst offenders. AWT doesn't always behave the same even in the Sun implementations; it's an abstract layer over the native widgets, which often have completely different native APIs.
For example, six years ago, when I was new to Java, I wrote a widget that dragged a tile from one area to another. My implementation attempted to hand MouseListener from one Component to another ... and it worked great, on Solaris/Motif. Unfortunately, as my boss was demoing this to the entire group on Windows NT, the tile wouldn't drag. Shamefaced, I went back and rewrote the app to avoid the handoff.
Swing was intended to fix the problems of AWT by reimplementing all widgets in Java, but it's fundamentally based on java.awt.Component and other AWT infrastructure. It's still subject to the same subtle differences in mouse, keyboard, and graphics behavior.
There are probably similar problems with using native threads, and I'm sure others can cite more obscure examples.
Would better Java conformance tests catch these variations? Honestly, I can only imagine finding these problems after the fact, and adding regression tests. I'm sure JVM vendors will also complain about tightening the certification tests, since it makes more work for them to emulate someone else's "default" behavior.
> all of these issues must be addressed separately > if the Java application is to run consistently and > smoothly in every platform that Java supports
Much of the reality of cross-platform GUI portability was already well understood from Smalltalk implementations before Java hyped "write once run everywhere".
VisualWorks Smalltalk already had the emulated widgets that would appear in Java. IBM VisualAge Smalltalk already had the option for native widgets that would reappear as SWT.
In retrospect, the big problem of Smalltalk - lack of standardization between vendors - avoided some illusions. No one expected to move UIs between different vendor implementations. We did expect and get portability between platforms (MS Windows, Apple Mac, 5 unices, now Linux and OSX with VisualWorks) including drag & drop ;-)
> I don't know if you're using JVM as a shorthand for the > whole Java spec. Bytecodes, etc. work pretty much the > same (modulo JIT/Hotspot bugs). On the other hand, > packages relying on OS-specific code can have different > behaviors on different platforms.
No, I think the language itelf is fine (or at least acceptable though there is room for improvement as we can see in the upcoming 1.5 release). I refer in my previous post to the implementation of the Java runtime environment on the various platforms and by the various vendors.
Not having implemented a JVM myself I'm not clear on the details (and, frankly, don't have any problems sleeping so have no real desire to read the spec in detail :-) but as near as I can tell the JVM spec can be a little fuzzy in places and leaves a lot of details up to the implementer. I have in mind things like garbage collection and threading as examples. I recall this causing some problem with Java code developed and tested on windows then going into production on *NIX systems, for example.
Would anyone who has read the spec and written a JVM care to comment?
One thing you can do is bundle a jre with your software (InstallShield does this, the jre is just used to run your program). This definitaly wouldn't eliminate cross-platform problems, but it would remove the need to check for the jvm version.