JWZ's complains can broadly be broken into 2 categories: Java lacks advanced programming features, and Java doesn't perform well.
Some of the features have been added (enums, weak pointers, etc) and some will probably never be added because they conflict with the overall design of the language (typedefs, macros, etc).
However, many-to-most of his performance complaints have become irrelevant due to a combination of better hardware (e.g. not needing to worry so much about small memory overheads) and a smarter VM (e.g. hotspot can inline entire branches of a call tree based on metrics it gathers at runtime).
One of JWZ's main Java experiences was trying to program a web browser in Java 1.0, IIRC. Since this was over 10 years ago, his main frustrations seemed to be with the fact that he didn't have enough control over the language to get it to perform well enough for this purpose.
Interestingly, most people I see choosing other languages over Java today don't care that Java performs better than their language of choice (it almost always does), but rather because their language of choice has convenient features which make it easier for them to write code, performance be damned. I came to Python from Java for this exact reason, and despite JWZ's valid frustration with 1990s Java performance, I can't help but read most of his essay and think "how quaint" at his performance concerns.
This is kind of off-topic, but I've been considering using Python precisely for the "easier to write code" reason, but I want to be cross-platform. I don't see any good way of making sure I have a Python interpreter of the right version with the appropriate libraries (audio, visual, UI, sci-py, etc.) unless I ship everything--libraries and interpreter. Is there a good way of handling that with Python? It seems like Java makes it a lot easier (except that the UI looks so bad I'd be ashamed to ship anything with it).
Another possibility is trying a different JVM language.
Jython, of course, tries to implement Python directly on the JVM. Scala and Clojure are two higher level languages (than Java) that run on the JVM with all the deployment advantages and library availability of Java. One of these might be a good way to have your cake and eat it, too.
Summation: There have been modest improvements, but most of the fundamental objections JWZ had are still in force, in particular the ones about the nature of the language itself. After learning Python, Perl, Haskell, and sundry others I've come to consider the "It's hard to live with none of: lexically scoped local functions; a macro system; and inlined functions." criticism the most devastating, and the only progress on that front is that Java may or may not get closures in the future, and if it does they will probably have many issues.
I also think the top answer misses the point of JWZ's criticism about inlining; his complaint is not that JVMs don't inline, but that he can't control it. A commenter further down on the page points out that in C++ it's only a hint and I suspect JWZ wouldn't appreciate that either. Standard caveat: I'm trying to guess what somebody else "really means" and that's always tricky, my apologies if I get it wrong.
I agree that Java suffers greatly from the absence of closures. However, I also fear that Java is designed in such a way, and has so much existing code, that it may be near impossible to add closures in a way that isn't confusing and doesn't break in unexpected ways.
Joshua Bloch thoroughly covers the relevant issues in these PowerPoint slides.
"First the good stuff: Java doesn't have free(). I have to admit right off that, after that, all else is gravy. That one point makes me able to forgive just about anything else, no matter how egregious. Given this one point, everything else in this document fades nearly to insignificance."
His argument that "there are four completely different things that go by the name 'Java'", and about Sun's incompetence at positioning it is still pretty devastating.
I pine for an alternate universe where Sun deftly parried Microsoft's Java to their benefit instead of repeatedly screwing themselves over. Sure, MS management wanted to fuck over Sun, but the grunts writing the software really legitimately wanted Java to be the best language to write GUI apps in for Windows. Unfortunately the language itself was nowhere near ready for that (much less the standard libraries), so they improved the language. Sun promptly freaked the fuck out.
The end result is that progress was delayed by a decade (especially on Windows), and Microsoft ended up with sole control over the only decent industrial development platform for GUI applications.
The world would be a much better place if C# and the CLR were forks of Java and the JVM, with features percolating in both directions towards eventual standardization.
Some of the features have been added (enums, weak pointers, etc) and some will probably never be added because they conflict with the overall design of the language (typedefs, macros, etc).
However, many-to-most of his performance complaints have become irrelevant due to a combination of better hardware (e.g. not needing to worry so much about small memory overheads) and a smarter VM (e.g. hotspot can inline entire branches of a call tree based on metrics it gathers at runtime).
One of JWZ's main Java experiences was trying to program a web browser in Java 1.0, IIRC. Since this was over 10 years ago, his main frustrations seemed to be with the fact that he didn't have enough control over the language to get it to perform well enough for this purpose.
Interestingly, most people I see choosing other languages over Java today don't care that Java performs better than their language of choice (it almost always does), but rather because their language of choice has convenient features which make it easier for them to write code, performance be damned. I came to Python from Java for this exact reason, and despite JWZ's valid frustration with 1990s Java performance, I can't help but read most of his essay and think "how quaint" at his performance concerns.