I think everybody hates Java as a desktop thing. I see Java mentioned a lot lately, but all of the mentions within the last year have been of Java as a server language, not as a desktop language. If you go back a year and a half, everybody was talking about Java on the desktop. They aren’t anymore. It’s dead. And once you’re dead on the desktop, my personal opinion is you’re dead. If servers are everything you have, just forget it. Why do you think Sun, HP — everybody — is nervous about Microsoft? It’s not because they make great servers. It’s because they control the desktop. Once you control the desktop, you control the servers.
It’s no longer something that will revolutionize the industry. It could have revolutionized the industry if it was on the desktop, but I don’t see that happening anymore. I hope I’m wrong. Really. I just don’t think I am.
—Linus Torvalds, 1998
A company should build a process that systematically looks at every product, every service, every process, every policy, every market with the question, “If we weren’t doing this already, knowing what we now know, would we start it, would we go into it?” If not, how quickly can we get out?
At first glance, Java looks quite like C, and very much like Microsoft’s C#. Sun’s Java adopted much of the syntax and semantics of C but added object orientation and many other language innovations, including garbage collection, and they made no effort to be 100% backwards compatible like C++ did.
While Java has many important technical advancements, it has achieved only a small fraction of the universal status it should have. Java should have replaced C and C++, languages desperate to be taken out back and shot! However, Java did not, and one of the biggest reasons why software is in shambles today is because Sun repeatedly screwed the pooch with Java.
In mid-2006, after Scott McNealy’s departure as CEO, Sun began making Java free, attempting to solve some of the issues mentioned in this chapter, but Java grew up as proprietary and this has left indelible scars on it. I will discuss why making it free won’t change things at the end of the chapter.
For those not in the software business, it is hard to describe the ire many programmers have felt towards Sun. This frustration is rooted in the special part tools play in the life of a software developer. A programmer is a tinkerer; he tinkers with his own tools as much as he concentrates on the job at hand. Software tools are continuously refashioned. If I need to process columns of data in a text file I receive from the Internet, it is almost as easy to fashion a tool to accomplish the task as it is to do it by hand. (A spreadsheet would be a useful tool, but there are other possible ones. A web server isn’t going to load a spreadsheet to extract and process simple data from a text file.) A suitable tool might not exist, or might not be exactly suitable to the particular task until it is tinkered with and made into the proper tool for the job.
Sun locked up the code
Brilliance is typically the act of an individual, but incredible stupidity can usually be traced to an organization. —Jon Bentley
Sun’s first mistake was that they failed to do what Bell Labs did with C and C++: create freely available compilers and runtimes for people to experiment with and extend. Instead, Sun locked up the Java codebase, letting few see it, and letting even fewer improve it, so that today, there exists only a small community of people, outside of Sun itself, improving Java.
For example, because Sun locked up their code, no one was able to port it to other processors. As I mentioned in the Linux chapter, Debian calls itself “The Universal Operating System” because it contains 18,000 software components that run on 15 different processor architectures:
Intel x86 / IA-32
Renesas’s 32-bit RISC
Debian supports 15 processors, but Sun’s Java web page lists just four.
A wide variety of platforms allow the programmer to decide which processor is the best choice for his product. By contrast, on Sun’s website, you can only download four architectures: x86, PowerPC, AMD64 and Sparc.
The fact that Java doesn’t offer broad support on hardware platforms is a significant consideration. Why invest in a programming language that might not be usable with future hardware? C, and other free languages, provide tremendous hardware flexibility in their widespread adoption.
Flexibility and adaptability of programming tools is especially important for embedded devices because, unlike the PC environment where processors and operating systems have similar functionality, the software must be customized for embedding on low-end hardware, something that Sun did not enable.
For its first five years, when everyone was seriously considering using it, Java ran ten times slower than C because it was interpreted rather than compiled, exactly like Lisp. This would have been fixed a lot faster if Sun had involved and encouraged the existing free compiler development community.
Even in 2008, Java programs on my computer don’t look like they should. For example, when a program asks to display a file chooser dialog box to the user, below are the results for a Java and a native application:
Java had many significant limitations for many years because all progress was held up by Sun.
Sun obsessed over specs
A “spec” is close to useless. I have never seen a spec that was both big enough to be useful and accurate.
And I have seen lots of total crap work that was based on specs. It’s the single worst way to write software, because it by definition means that the software was written to match theory, not reality. So there’s two MAJOR reasons to avoid specs:
1. They’re dangerously wrong. Reality is different, and anybody who thinks specs matter over reality should get out of kernel programming NOW. When reality and specs clash, the spec has zero meaning. Zilch. Nada. None.
It’s like real science: if you have a theory that doesn’t match experiments, it doesn’t matter how much you like that theory. It’s wrong. You can use it as an approximation, but you MUST keep in mind that it’s an approximation.
2. Specs have an inevitable tendency to try to introduce abstractions levels and wording and documentation policies that make sense for a written spec. Trying to implement actual code off the spec leads to the code looking and working like CRAP.
The classic example of this is the OSI network model protocols. Classic spec-design, which had absolutely zero relevance for the real world. We still talk about the seven layers model, because it’s a convenient model for discussion, but that has absolutely zero to do with any real-life software engineering. In other words, it’s a way to talk about things, not to implement them.
And that’s important. Specs are a basis for talking about things. But they are not a basis for implementing software. So please don’t bother talking about specs. Real standards grow up despite specs, not thanks to them.
Imagine designing a car by a committee on a computer, and then sending the design directly to the assembly line without building a car first and letting anyone test-drive it.
Sun didn’t let anyone read or tinker with their code but they wanted to be seen as a community-oriented effort, so, they created the Java Community Process where human-readable specifications describing Java were produced. Unfortunately, they focused on the specs and not on releasing software for people to try out so that the feedback came years later, or not at all. The biggest feedback that Sun would have received, but did not, was how insanely complicated their Java specs were. As an example, here is what a menu item looks like on the screen:
and here are the 456 functions a Java MenuItem class implements:1
action, actionPropertyChanged, add, addActionListener, addAncestorListener, addChangeListener, addComponentListener, addContainerListener, addFocusListener, addHierarchyBoundsListener, addHierarchyListener, addImpl, addInputMethodListener, addItemListener, addKeyListener, addMenuDragMouseListener, addMenuKeyListener, addMouseListener, addMouseMotionListener, addMouseWheelListener, addNotify, addPropertyChangeListener, addVetoableChangeListener, applyComponentOrientation, areFocusTraversalKeysSet, bounds, checkHorizontalKey, checkImage, checkVerticalKey, clone, coalesceEvents, computeVisibleRect, configurePropertiesFromAction, contains, countComponents, createActionListener, createActionPropertyChangeListener, createChangeListener, createImage, createItemListener, createToolTip, createVolatileImage, deliverEvent, disable, disableEvents, dispatchEvent, doClick, doLayout, enable, enableEvents, enableInputMethods, equals, finalize, findComponentAt, fireActionPerformed, fireItemStateChanged, fireMenuDragMouseDragged, fireMenuDragMouseEntered, fireMenuDragMouseExited, fireMenuKeyPressed, fireMenuKeyReleased, fireMenuKeyTyped, firePropertyChange, fireStateChanged, fireVetoableChange, getAccelerator, getAccessibleContext, getAction, getActionCommand, getActionForKeyStroke, getActionListeners, getActionMap, getAlignmentX, getAlignmentY, getAncestorListeners, getAutoscrolls, getBackground, getBaseline, getBaselineResizeBehavior, getBorder, getBounds, getChangeListeners, getClass, getClientProperty, getColorModel, getComponent, getComponentAt, getComponentCount, getComponentGraphics, getComponentListeners, getComponentOrientation, getComponentPopupMenu, getComponents, getComponentZOrder, getConditionForKeyStroke, getContainerListeners, getCursor, getDebugGraphicsOptions, getDefaultLocale, getDisabledIcon, getDisabledSelectedIcon, getDisplayedMnemonicIndex, getDropTarget, getFocusCycleRootAncestor, getFocusListeners, getFocusTraversalKeys, getFocusTraversalKeysEnabled, getFocusTraversalPolicy, getFont, getFontMetrics, getForeground, getGraphics, getGraphicsConfiguration, getHeight, getHideActionText, getHierarchyBoundsListeners, getHierarchyListeners, getHorizontalAlignment, getHorizontalTextPosition, getIcon, getIconTextGap, getIgnoreRepaint, getInheritsPopupMenu, getInputContext, getInputMap, getInputMethodListeners, getInputMethodRequests, getInputVerifier, getInsets, getItemListeners, getKeyListeners, getLabel, getLayout, getListeners, getLocale, getLocation, getLocationOnScreen, getMargin, getMaximumSize, getMenuDragMouseListeners, getMenuKeyListeners, getMinimumSize, getMnemonic, getModel, getMouseListeners, getMouseMotionListeners, getMousePosition, getMouseWheelListeners, getMultiClickThreshhold, getName, getNextFocusableComponent, getParent, getPeer, getPopupLocation, getPreferredSize, getPressedIcon, getPropertyChangeListeners, getRegisteredKeyStrokes, getRolloverIcon, getRolloverSelectedIcon, getRootPane, getSelectedIcon, getSelectedObjects, getSize, getSubElements, getText, getToolkit, getToolTipLocation, getToolTipText, getTopLevelAncestor, getTransferHandler, getTreeLock, getUI, getUIClassID, getVerifyInputWhenFocusTarget, getVerticalAlignment, getVerticalTextPosition, getVetoableChangeListeners, getVisibleRect, getWidth, getX, getY, gotFocus, grabFocus, handleEvent, hasFocus, hashCode, hide, imageUpdate,fireMenuDragMouseReleased isBorderPainted, init, insets, inside, invalidate, isAncestorOf, isArmed, isBackgroundSet, isContentAreaFilled, isCursorSet, isDisplayable, isDoubleBuffered, isEnabled, isFocusable, isFocusCycleRoot, isFocusOwner, isFocusPainted, isFocusTraversable, isFocusTraversalPolicyProvider, isFocusTraversalPolicySet, isFontSet, isForegroundSet, isLightweight, isLightweightComponent, isManagingFocus, isMaximumSizeSet, isMinimumSizeSet, isOpaque, isOptimizedDrawingEnabled, isPaintingForPrint, isPaintingTile, isPreferredSizeSet, isRequestFocusEnabled, isRolloverEnabled, isSelected, isShowing, isValid, isValidateRoot, isVisible, keyDown, keyUp, layout, list, locate, location, lostFocus, menuSelectionChanged, minimumSize, mouseDown, mouseDrag, mouseEnter, mouseExit, mouseMove, mouseUp, move, nextFocus, notify, notifyAll, paint, paintAll, paintBorder, paintChildren, paintComponent, paintComponents, paintImmediately, paramString, postEvent, preferredSize, prepareImage, print, printAll, printBorder, printChildren, printComponent, printComponents, processComponentEvent, processComponentKeyEvent, processContainerEvent, processEvent, processFocusEvent, processHierarchyBoundsEvent, processHierarchyEvent, processInputMethodEvent, processKeyBinding, processKeyEvent, processMenuDragMouseEvent, processMenuKeyEvent, processMouseEvent, processMouseMotionEvent, processMouseWheelEvent, putClientProperty, registerKeyboardAction, remove, removeActionListener, removeAll, removeAncestorListener, removeChangeListener, removeComponentListener, removeContainerListener, removeFocusListener, removeHierarchyBoundsListener, removeHierarchyListener, removeInputMethodListener, removeItemListener, removeKeyListener, removeMenuDragMouseListener, removeMenuKeyListener, removeMouseListener, removeMouseMotionListener, removeMouseWheelListener, removeNotify, removePropertyChangeListener, removeVetoableChangeListener, repaint, requestDefaultFocus, requestFocus, requestFocusInWindow, resetKeyboardActions, reshape, resize, revalidate, scrollRectToVisible, setAccelerator, setAction, setActionCommand, setActionMap, setAlignmentX, setAlignmentY, setArmed, setAutoscrolls, setBackground, setBorder, setBorderPainted, setBounds, setComponentOrientation, setComponentPopupMenu, setComponentZOrder, setContentAreaFilled, setCursor, setDebugGraphicsOptions, setDefaultLocale, setDisabledIcon, setDisabledSelectedIcon, setDisplayedMnemonicIndex, setDoubleBuffered, setDropTarget, setEnabled, setFocusable, setFocusCycleRoot, setFocusPainted, setFocusTraversalKeys, setFocusTraversalKeysEnabled, setFocusTraversalPolicy, setFocusTraversalPolicyProvider, setFont, setForeground, setHideActionText, setHorizontalAlignment, setHorizontalTextPosition, setIcon, setIconTextGap, setIgnoreRepaint, setInheritsPopupMenu, setInputMap, setInputVerifier, setLabel, setLayout, setLocale, setLocation, setMargin, setMaximumSize, setMinimumSize, setMnemonic, setModel, setMultiClickThreshhold, setName, setNextFocusableComponent, setOpaque, setPreferredSize, setPressedIcon, setRequestFocusEnabled, setRolloverEnabled, setRolloverIcon, setRolloverSelectedIcon, setSelected, setSelectedIcon, setSize, setText, setToolTipText, setTransferHandler, setUI, setVerifyInputWhenFocusTarget, setVerticalAlignment, setVerticalTextPosition, setVisible, show, size, toString, transferFocus, transferFocusBackward, transferFocusDownCycle, transferFocusUpCycle, unregisterKeyboardAction, update, updateUI, validate, validateTree, wait
The list of functions the Swing Java MenuItem class implements, with bizarro names like “isFocusTraversalPolicyProvider” and “addVetoableChangeListener”. Imagine if you needed to become familiar with 456 things to use your oven.
Such bloated code is hard to understand and even harder to make reliable. And this is just the Swing class library’s opinion of a menu item, one of three popular implementations of Java widgets, and supposedly an efficient one!
Java is plagued by too much complexity as you can see, and releasing specs instead of code is a big cause of this problem. In fact, many of the Java specs aren’t widely used because they do not meet developers’ needs, or they became heavily amended after they finally got into customers’ hands, which was often years after the specs were originally written.2
Java was not growing carefully and organically, as Linux has done, by following the “ship early, ship often” methodology. A lot of people who hate Java do so because of its pervasive extraneous complexity.
Sun locked up the design
When it created Java, Sun didn’t want to release the code because they were worried people would take their code, tweak it slightly to better meet their needs, and create incompatibilities that would hurt the “brand” of Java — confusing a 99% friend with an enemy. This paranoia occurred because Sun made a rookie mistake in not understanding that a language needs to be extensible.
In the C and C++ world, there is even a convention that any non-standard keywords would be prefaced with two underscores, like this: “__inline”. In some cases, a feature started out as a vendor-specific addition, was adopted by others, and eventually became added to the language in an official way. The creators of C and C++ didn’t have the hubris to believe they had built a perfect language.
Even more importantly, the primary way to extend a computer language is by creating new functions and data types, which was also not allowed in any of the domains specified by Sun.
Sun got it backwards — people will only make minimal changes necessary to Java to make it work for them. That is what happened in C and C++. Sun didn’t have faith in its customers and didn’t understand the realities of how large bodies of systems-level code are created.
Sun fragmented Java
Because of fear, Sun decided to lock up their code to prevent it from being extended by anyone else. This short-sighted idea, but even worse, the law of unintended consequences came up and bit them in the tush. Because Sun made only the specs but not the code available, many third parties started producing their own Java runtimes so they could control their own destiny. Wikipedia documents 34 different third-party Java runtimes, and their list doesn’t include any of the embedded Java implementations, which are harder to count.
Everyone who wanted to use but improve Java would have to start from scratch. This created much bigger areas of incompatibility because building a Java implementation from scratch requires a lot of work, and they could even unknowingly cut corners.
The biggest problem with so many runtimes, besides the wasted efforts, is that the imperfect specs became the reference rather than the code because there wasn’t an agreed upon codebase containing the official Java design.
Backward compatibility is the greatest cause of complexity, and therefore unreliability, in computers today. As described in the Linux chapter, one of the Linux kernel’s major innovations is that it avoids backward compatibility issues by encouraging all code into one tree. This makes it much easier to make changes to the design.
With an official source tree, Java could become whatever we need it to be, avoiding the mess of different codebases, and serving as a reference when the paper specs are ambiguous. It sounds chaotic, but things quickly converge, and on something with minimal excess complexity, because it can be removed.
While the Java specs were not good because feedback came years later, they became etched in stone because once 30 runtimes have a particular piece of functionality, it becomes very hard to change them all. Even if Sun let you alter their design, it might take years to make any changes. In contrast, if the Linux kernel is missing a feature, you can send some code to Linus and have it in the official codebase immediately.
Sun sued Microsoft
Another Sun mistake was getting into a war with Microsoft over Java. Microsoft’s tools division was an active participant in Java for its first several years, and PC Magazine wrote in 1997 that: “Microsoft’s Java environment was the fastest and most compatible on our tests.”
When Microsoft improved Java in certain ways that by definition were incompatible, Sun sued them. Microsoft’s changes to Java were minor, the features justifiable, and the incompatibilities almost non-existent.3
A public lawsuit, the exchange of $20 million in damages, and much bitterness ensued.
Eventually, Microsoft quit supporting Java and went off to create C# instead. C# might be considered Java 2.0. While it is very similar to Java, it had five years of refinement and applied Microsoft’s many years of experience as a dominant force in the tools business. C# created unnecessary chaos and confusion in the industry and allowed Microsoft to be 100% incompatible with Java rather than just .01% incompatible. Microsoft would not have created C# if Sun hadn’t sued them.
Java as GPL from Day 0
If Sun had created Java with a GPL license, the landscape of the software industry would look completely different today, and computers would be more reliable and smarter. Java would be more reliable, simpler, richer, and faster, and a community, like C and C++, that Microsoft tools developers would have been a part of.
The success of C was in part due to its widespread support, which made it easier to share code than did its predecessor on the PC — assembly language. It is hard to share code across languages, and the proliferation of new ones has gotten worse since Java was created, when it should have gone in the opposite direction.4
Even within Sun, there is a group of people trying to build another programming language called Fortress, which will be suitable for scientific computing. They too believe Java is not sufficient as it is.5
Pouring Java down the drain
The Lord said, “If as one people speaking one language they have begun to do this, then nothing they plan to do will be impossible for them.” Genesis 11:66
Scott McNealy, co-founder and CEO of Sun Microsystems from 1984 – 2006, and an impediment to free software — even though his company made most of their money on hardware.
Sun’s first major decision after co-founder Scott McNealy’s departure in mid-2006 was a promise to make much of their software, including Java, free. This announcement was big news and some think it marks the potential for a new day in the life of Java. However, this effort is starting more than a decade after Java’s creation, arguably too late to fix most of the problems.
Even with Sun’s new GPL license, there is a lot of Java code out there that is not free and cannot be made so by Sun. Apple, for example, took Sun’s PC implementation and worked extensively to port it to Macintosh. This code isn’t free, and it doesn’t seem likely that Apple will ever make it such. There is a company making Java run on mainframes, and their enhancements are proprietary as well. Even within the code Sun has recently made free, there are pieces Sun licensed from third parties, and they are having to re-write it because they can’t get permission to change the license.
Even a free Java on its current trajectory will not absorb other communities. C# is considered better than Java, so those programmers are not making a switch. There are millions of web pages written in PHP, and I don’t see them rushing to switch to Sun’s Java either. Sun’s code has been locked up for so long, there are few people in the outside world able to contribute. Why should the community fix a mess that was created only because Sun didn’t work with the community in the first place?
C# and .Net is the dominant platform on Windows, PHP is the dominant language on the Web, and Python and Mono are the most popular GC runtimes on the Linux desktop. So while Java is taught in universities, used for custom applications in enterprises, and has some success on mobile phones, these niches aren’t enough to to ensure its long-term viability. Java has accumulated so much baggage, only some of which I have discussed here, that I think the software community should abandon it. This would also take a big step in lessening the problem of too many programming languages. In earlier drafts of my book, I proposed Sun create a next generation programming language, but I now believe there already are suitable codebases: Mono and Python.
Warning from 2013, this is old text from 2008. I no longer recommend anyone use Mono. However, it was sad to build such a nice runtime and then be afraid to use it even after Microsoft had promised not to sue! Etc.
Mono and Python
Today, the most popular GC runtimes on the Linux desktop today are Mono and Python. Both are built by a worldwide community, but each has certain advantages and disadvantages.
One of Mono’s biggest advantages is that it is compiled. While performance is not the most important factor of software quality, any language which wants to become the standard for Linux needs a compiler. Even if only a small fraction of any piece of software is performance-critical, the language doesn’t know what that part is, and so it should run all code fast. Another advantage of Mono is that it comes with a complete end-to-end solution for creating programs: a graphical editor and debugger, code browser with auto-complete, etc. With Python, you must piece together these components yourself, and there isn’t a standard one with critical mass.
Mono’s biggest disadvantage stems from the fact that it is an implementation of .Net which is a standard created by Microsoft. The C# language and the core libraries are not created with much input from the worldwide community and the enhancements are improved only on Microsoft’s schedule. Microsoft has hired some of the best language designers on the planet, like Anders Hejlsberg, but he is not as smart as the combined knowledge of the rest of the languages designers on the planet. This has practical effects: C# added “dynamic language” features in the version 4.0 of the language, while Python has had these for many years.7
Another “disadvantage” of Mono is that there is an enormous amount of FUD (fear, uncertainty and doubt) that surrounds it. Microsoft has historically been hostile towards free software, calling it a “cancer” and sometimes threatening to sue over claimed patent infringements, and while this should create fear all over the free software stack, it appears to be directed mostly at Mono! I believe Linux programmers are being irrational because the .Net specification is publicly available, and Microsoft has repeatedly promised not to sue for implementations of it. Programmers should also realize that Mono extends the reach of .Net to other processors and operating systems, which benefits Microsoft’s customers.
Python’s advantage is that it is created with input from programmers all over the world, and has a larger set of libraries than any other GC language:
A computational fluid dynamic (CFD) visualization of a combustion chamber. The Python community has quietly created a wide variety of libraries for everything from gaming to scientific computing. There are even books to teach it to 8-year olds.
Python’s biggest disadvantage is performance: it is not compiled and doesn’t support multiple threads. These features are a requirement for any serious runtime and so one might wonder whether Python is still at a prototype phase of development. Even fans of Python very loudly complain that while it might be suitable for little scripts and application plugins, it is too slow for writing large applications.
These features are a big amount of work that are not even on Python’s to-do list. And as the language has never been compiled there are even some questions as to whether it can be made fast.8
In addition, Because the Python runtime is slow, the developers are forced to write a lot of support code in C, which further slows its development progress. Is is a shame that Python isn’t fully using a tool which would have made their job easier — their own language. There are efforts such as the PyPy project which has built a Python compiler, in Python, which outputs C. Unfortunately, this piece of elegance is not yet the mainline codebase and is not considered for such.9
And as mentioned earlier, the language doesn’t have a standard graphical programming and debugging environment. So Python today has impediments for both casual programmers looking for an easy way to get into programming, and professionals who care about building high-performance applications.
There are other interesting languages and runtimes out there, but I believe the Linux desktop community should focus on these two. Mono already supports other languages in addition to C#, some that even look like Python.
There are many good programming languages, in fact there are too many, but I also think they a number are good enough. One could further tweak the letter of the English language to make it easier for your eyes to distinguish the letters, and simplify the pronunciation rules, but it isn’t necessary because what we have is good enough. Likewise, it is much more important to build a complete set of libraries for all aspects of computing, a Wikipedia of free code, than to worry that further language innovation is the gating factor towards any future progress in software. Paul Graham and others view programming languages as a continuum of richness and elegance, but that isn’t really true; Lisp is still considered one of the best programming languages, in spite of its age, so we must reach a point of diminishing returns. In general, the way you extend a programming language is with new functions.
Let’s Start Today
All economic activity is by definition “high risk.” And defending yesterday — that is, not innovating — is far more risky than making tomorrow.
When there’s a will to fail, obstacles can be found.
Sometimes the real hurdle to renewal is not a lack of options, but a lack of flexibility in resource allocation. All too often, legacy projects get richly funded year after year while new initiatives go begging. This, more than anything, is why companies regularly forfeit the future — they over invest in “what is” at the expense of “what could be.” New projects are deemed “untested”, “risky”, or a “diversion of resources.” Thus while senior execs may happily fund a billion-dollar acquisition, someone a few levels down who attempts to “borrow” a half-dozen talented individuals for a new project, or carve a few thousand dollars out of a legacy budget, is likely to find the task on par with a dental extraction.
The resource allocation model is typically biased against new ideas, since it demands a level of certainty about volumes, costs, timelines, and profits that simply can’t be satisfied when an ideal is truly novel. While it’s easy to predict the returns on a project that is a linear extension of an existing business, the payback on an unconventional idea will be harder to calculate. Managers running established businesses seldom have to defend the strategic risk they take when they pour good money into a slowly decaying business model, or overfund an activity that is already producing diminishing returns. How do you accelerate the redeployment of resources from legacy programs to future-focused initiatives? —Gary Hamel, The Future of Management
When software, the most important building block of mankind’s intellectual property, uses a standard GC programming language and protects itself with copyleft, mankind will enter a shining age. I think better runtimes are critical to the success of Linux on the desktop.
Unfortunately, fixing this problem is a big task because inertia is such a powerful force. The good news is that the difficulty of porting to a different language is not the same in every case. Porting from one modern language to another is ten times easier than moving from C to C#. Right now, much of our code and infrastructure lives in the dark ages, and this first port is the hardest, but it will provide big benefits.
During my tenure at Microsoft, I witnessed numerous re-writes. Unfortunately, most of them failed. Those that failed had at least one thing in common: they usually were re-writing C code in C, or C++, and because they did not use significantly better tools as part of their plan, they never ended up saving any time in the end. It doesn’t make sense to re-build something from scratch unless you plan to make it a lot better. But if the teams out there move from C or C++ to a much more productive language, they will save time in the end and it is much more likely to succeed — assuming they start. The key is to make a plan and break down the problem.
1 Other widget libraries, like the Gtk#’s MenuItem have hundreds functions as well, but many do not and Java is the worst. The WxWidgets MenuItem class has 50 members, and it uses native widgets on Mac, Windows and Linux. Apple’s NSMenuItem has 55.
2 Two good examples of basically unused class libraries are:
1. JXTA, Java’s peer-to-peer protocol that standardizes many aspects of P2P but is not used because it solves the wrong problems, and,
2. J2ME, Java’s underpowered class library for mobile devices which has primitive widgets, is unable to access a phone’s address book, calendar, camera, GPS, or web browser, and has no ability to make phone calls. J2ME’s goal should be rich enough to build an entire phone user interface in Java, but it only has the ability to make toy applications, and even then, programmers often complain that the differences between the implementations make it a “write once, test everywhere” scenario.
3 One of the things Microsoft changed was to simplify and improve the performance of how a Java developer called in to native operating system functionality. Java has always allowed developers to write non-portable, operating system-specific code when the operating system provided a feature that a developer wanted access to but that Java did not support. By definition this code was not cross-platform, so one would imagine that Microsoft-specific syntax to access Windows-specific features would not have been a big deal. In fact, the way a Java programmer would call the native functionality on Windows had the same syntax between Microsoft’s RNI and Sun’s JNI. It was only the way the native method was declared that was different. Microsoft did make other changes, such as adding a keyword, “delegate”, but if you search the web you can find many people who wished Sun had added that feature and code samples to enable that feature in Java.
4 Sharing code across languages has historically been very difficult. The search engine Lucene is a recent example of something which started in Java but has been forked into versions in PHP and C#.
There are many reasons for it being so difficult to share code between different languages. They have different ways of deploying the code, different naming conventions, and different low-level details. Interoperating layers usually adds significant performance costs because everything from the strings on up the stack have to be marshalled, which usually involves making a copy of the data. If you can’t agree on what a string is, then you will have difficulty sharing code. (Going from C# to C/C++ is fast because a copy of the data doesn’t need to be created — a C Unicode string is a subset of a C# string.)
5 Fortress’s syntax is arbitrarily different from Java in ways not at all related to high performance computing (HPC). A programming language is by definition extensible by creating new functions and classes, and it is also possible to alter the runtime, without changing the language, to optimize it for specialized hardware, etc. The big challenge in HPC is to robustly divide up the work amongst a farm of servers, pass messages and maintain and monitor the system — new software, not new language features.
6 My bible says God scattered the Babylonians because of their “pride.” I can’t know what they thought, but I do believe that learning about ourselves, using technology to save and improve lives, and attempting to understand the true nature of the world, only gives us more appreciation for what He has created. I believe the creator of liberty and science wants us to understand these concepts, as long as we don’t lose track of our relationship with the creator somehow in the process.
7 One other concern about Mono is that it doesn’t use a copyleft license. Excerpt from the FAQ on the Mono website:
“When a developer contributes code to the C# compiler or the Mono runtime engine, we require that the author grants Novell the right to relicense his/her contribution under other licensing terms. This allows Novell to re-distribute the Mono source code to parties that might not want to use the GPL or LGPL versions of the code. Particularly: embedded system vendors would obtain grants to the Mono runtime engine and modify it for their own purposes without having to release those changes back.”
8 In some performance tests, the IronPython implementation on .Net runs slower than the standard Python implementation. So even though IronPython has access to a compiler, it apparently isn’t able to take advantage of it enough to be faster.
Brilliant analysis. Strong writing skills. Thank you very much.
No offense, but IMHO, footnote #6 should rather be removed.
I agree. Brilliant.
However, I believe footnote #6 is relevant to this story because the Babylonians were scattered because of their language differences. Their project was abandoned because they could no longer communicate with each other.
Excellent article! It isn’t often I read an article that I think is balanced and backed up with good examples. It was a good read. Well done.
I was with you right until you wrote:
“I believe Linux programmers are being irrational because the .Net specification is publicly available, and Microsoft has repeatedly promised not to sue for implementations of it.”
Microsoft has a shrewd group of lawyers. If they sue, then their rivals can countersue. To avoid countersuits Microsoft funds intermediaries to sue on their behalf. For instance, SCO was well funded to sue IBM, Novell, and others by Microsoft and Baystar.
Having pushed copyright law to the limit, Microsoft has now turned its attention to patent law. Here are three examples:
1) Intellectual Ventures is a NPE who is only in business to bully and sue companies that innovate. Their funding comes from Microsoft executives.
2) Microsoft started litigation with TomTom over FAT. This suit would never have been brought if the patent system wasn’t broken in the first place.
3) Microsoft uses its proxy Acacia subsidiary IP Innovation to go after RedHat and Novell.
Why would you think that Microsoft would not come after the Linux community over Mono? Is it the covenant not to sue that they signed with Novell (before they bought and divided the company up)? Are you ignoring the past history of Microsoft? Are you ignoring Steve Ballmer’s comments when he said that every user of the open source Linux system could owe his company money for using its intellectual property.
I am not being irrational. I am using the facts to make a rational decision. Microsoft is a convicted monopolist on multiple continents, which routinely follows policies such as “embrace, enhance, extinguish” and “fear, uncertainty, doubt” at all levels of their business.
How about ISO, BSA, etc? It is possible that your former relationship with Microsoft has clouded your judgement. If you are not willing to consider the facts, then it is you who is irrational.
I’m not defending Microsoft, only defending the idea that after the community has built Mono we should not throw it away. How often do you cook a meal and throw it in the trash instead of eating it?
…Python’s biggest disadvantage…and doesn’t support multiple threads…” Sorry, you’re not correct there. Python does support multiple threads. See http://www.devshed.com/c/a/Python/Basic-Threading-in-Python/ and http://www.artfulcode.net/articles/multi-threading-python/
I try to be correct without having too much jargon, but sometimes I fail. I will tweak the language (about the GIL) in a future version. Thanks for noting it.
So, in the end, should we all stick to C/C++ ? Or maybe just be open-minded without waiting for better times (improved languages or simply new better languages) ?
Giving up on popular modern solutions only because they are “closed” or owned by monopolists can make a breakthrough, but it takes time and it is unlikely possible only with bunch of geeks. Besides, creating “the one and only” language fails when facing the fact of lack of communication of programmers. Everybody is different,
Today, I recommend people use 99% Python + 1% C. Basically, build the whole thing in Python, and find little spots to port back.
[…] This post was mentioned on Twitter by Dr. Roy Schestowitz, Open Trends. Open Trends said: The Java Mess http://ping.fm/LN3yt […]
Feels like I knew very little about Java before reading this.. thanks.
How does Oracle suing Google over Java on Android fits into this discussion?
There have been major improvements to Java since it was open-sourced.
The screenshot of the file chooser dialog differences between Java and GTK applies only to Java <= 6: Java 7 will use the GTK file dialog (http://mail.openjdk.java.net/pipermail/awt-dev/2010-March/001191.html). Java 8 will have a better directory chooser dialog too.
Since Java was open-sourced, IBM (http://arstechnica.com/open-source/news/2010/10/ibm-joins-openjdk-as-oracle-shuns-apache-harmony.ars) and Apple have joined in to improve it. Red Hat has started the IcedTea project and contributed lots of improvements. The MacOS Java is now open-source too (http://openjdk.java.net/projects/macosx-port).
The third-party code rewrites are complete: OpenJDK no longer requires binary plugs to compile.
As for only 4 processors being supported, the Zero and Shark projects (http://openjdk.java.net/projects/zero/) have added support for Alpha, ARM, IA-64, MIPS, PowerPC, x86, x86-64 and zSeries. Other virtual machines using OpenJDK classes, such as IcedTea with CacaoVM, also supports the S390 (http://c1.complang.tuwien.ac.at/cacaowiki/CacaoFeatures).
Python suffers from the effects of its Global Interpreter Lock, which severely cripples performances with multiple threads. Mono's performance isn't great either, especially with floating point. IronPython might be slow in C#, but Java 7 will have an "invokedynamic" instruction allowing the JVM to optimize dynamically typed scripting languages running on the Java platform; JRuby is already seeing improvements.
You make it sound like a bad thing that Sun sued Microsoft. Microsoft was making Windows-only extensions to Java, and Sun's lawsuit kept Java unified and compatible with all platforms, which is the very point of Java. How is this a bad thing?
Thanks for the updates. I may fix it in the next revision of my book. Note the examples are still interesting for historical reasons even if no longer true.
As for your lawsuit question, I respond to it in a footnote:
I think the main reason why Sun made up a complex licensing model for JAVA was because the fear of their technology would be eaten like OS2/Warp, WordPerfect, Lotus, BeOS, BurstWare, DrDOS, NetWare, etc and the company end like IBM(but they had a later success thanks to JAVA), Borland, NetScape, Apple, AT&T, SCO, Burst, Be, Novell and others.
Lots of companies had good products but they were stealed or destroyed because predatory companies (not only Microsoft does that) were in the wild.
By design JAVA has a dangerous approach, the garbage collector and the automatic destruction feature (the same problems with the .NET garbage collector but eased in the C#). C# uses a mix of deterministic and undeterministic object destruction.
Those proprietary products weren’t eaten, they lost to superior proprietary products.
However, when something is free like the Linux kernel it can’t get destroyed like you suggest.
Thanks for this article which is factual and reassuring.
5 years back, in my bureaucratic workplace, I was a technically minded non-programmer. our ‘real-time’ order entry system was a shocking monstrosity from a bygone era. we lost a couple of hours a day at the terminal. mostly waiting on an old fashioned, server-side modem that would multiplex us with other sites around the country.
I successfully built a layer of automation on top of the frankenthing. Basically, I found expect. which exposed me to tcl. which ultimately led me to python.
I have always wondered, who chooses java out of a genuine practical need? who studies java for any reason except the university requires it? This article answers those questions with painful clarity.
I don’t have much of a problem with the syntax of Java; it’s the bloated, horrible libraries that drive me nuts and even worse is the marketing nonsense about it being so great.. it’s the libraries that have turned it into a steaming pile of poop… that being said, I don’t think it is impossible to create something great with Java (lookup ZK Framework for example..that’s about the only thing that makes Java look attractive to me).. it’s just much harder to do so and that’s why I have no inclination to ever use it again.
I think what we all really need is a framework like .NET but which can be used across all platforms. Thankfully, someone has already started the Mono project. Sure, it may have some issues.. but they are being tackled and I believe they will be overcome in time. There is always the right tool for the right job.. but imagine now with me for a moment… that not too long from now a dev can sit down and use his IDE to write code in any language he deems fit for the job and use code libraries that were written in any other language, including a base class library like .NET but edited by the open source community. This was a large part of the idea behind the .NET framework originally, but MS screwed it up by making it only work on Windows. Of course they would though, that’s where all their money comes from… so you can’t blame ’em I guess.. but if those of us with the skills to do so all work together on improving something like Mono.. it would be of such a great benefit to us and to future developers..
Look at what open source has achieved with projects like Linux.. imagine what we could do with an open source development platform.. that’s what we really need to be focusing on for the immediate future. For the sake of devs everywhere… for the sake of humanity.. (LOL) let’s start working together to make something great (and hopefully kill Java in the process)…
Hey OLD MAN. Didn’t we aleadry have this ? Didn’t we aleadry establish that your outmoded tendencies of grinding your own flour to bake a loaf of bread, looming your own fabric for a t-shirt, and managing your own memory references when programming run counter culture to the way the rest of us get things done every day? Do I need to spell it out to you in a null-terminated buffer of ASCII characters, lest you miss the end and I BLOW YOUR MIND?Seriously. OS hackers and computer scientists should know C and pointers and assembly and understand and the thousand other things that make System.out.println( Hello world! )’ work under the covers. But for high school students and software engineers, managed languages are the way to go.As Joel points: Now, I freely admit that programming with pointers is not needed in 90% of the code written today, and in fact, it’s downright dangerous in production code. OK. That’s fine. And functional programming is just not used much in practice. Agreed. You teach the 90% first and the hardcore 10% remainder will find a way to learn the rest like they always do. Teaching C first is like trying to teach someone to ride a bike by putting them on a fixed gear and pointing them down a hill in San Francisco. It’s too much too soon and it hides the real basics of what programming is about: flow control, algorithms, abstractions. Heck, I freely admit that even Java is too much too soon, but my colleagues here at UW who fret and worry about declining CS enrollment and do research about the best way to teach intro CS still pick Java before C.Also, get a haircut, you hippie.
“…Java ran ten times slower than C because it was interpreted rather than compiled, exactly like Lisp”.
This statement is inaccurate. Commercial Common Lisp is *not* interpreted, it is compiled into native code objects (often called “fasl” files) that are dynamically linked at run-time. Even when working within the Lisp environment, using the “listener”, expressions are usually (and in some cases always) compiled into native code before execution. There are also a number of open-source Lisp implementations that are *not* interpreted. In some situations, Common Lisp has been determined to be almost or exactly as fast as C.
Just wanted to clarify this point. Thanks for the article.
Java isn’t exactly a sparkling achievement after 50+ years of high-level language development.
I think Java is one of the best technologies the computer world have seen, it’s by far the most cross platform compatible, and the performance is one of the best also, that’s the reality, it has a huge library of good, mature libraries you can use to do pretty much everything. The battle against Java from Apple for example is that they can’t control it, a Java app will easily run on Windows, Mac, Linux etc, making the app ecosystem more abroad and not so controlled by Apple for example, as a consumer perspective, is the GUI, Java needs to make a better GUI, integration with the OSs is a must and that’s why swing GUI is not that good, but that can be better. Also is one of the most popular languages and at least here in Europe there’s plenty of Java programmers jobs requests. If they make some cool GUI effects aka Android, Java will kill!
Actually I take that back. Java does need a lot of work but actually it may be too late. Java has become a dinosaur and I believe it will die a slow death. My apologies for the previous rant. Its not just a GUI problem!
It IS too little too late. C# wins. Microsoft tried to improve upon it, and gets sued. Google stupidly picks java for android, and of course they can’t just use vanilla java or micro edition, so they have to improve it’s performance on there too. Result: they get sued (now by oracle). Java will die a slow death but oracle will make a huge lot of money on it, and programmers everywhere are dumber than generations prior thanks to it. Java – the new cobol and rpg