Hacker News new | comments | show | ask | jobs | submit login

A major cleanup of the Java libraries is scheduled for Java 9. The JVM actually does not surprise anyone who's been working with it for a while: it is downright the most performant, flexible and awesome runtime environment ever developed. I've been playing around with lots of languages and environments in my pretty long career and, in the past decade, have always come back to Java (or the JVM). It feels like driving a Ferrari where everything else is at best a Toyota - might be easier to handle at first, but it's not your dream car.

This pattern, by the way, has been going on in lots of tech companies. They always end up going back to the JVM.

Aside from terrific performance, the JVM gives you the best concurrency platform out there (though not the easiest to use), cool and extremely useful capabilities like dynamic linking and bytecode instrumentation, and unparalleled monitoring and profiling tools. It's the most professional platform you can choose (unless you're limited to Windows, in which case .Net is also an option). It's so far ahead than anything else out there, that the competition can only beat it in very specific use cases (e.g. Go is much better at startup time as well as standalone packaging, and C has better performance, though mostly in single-threaded programs). But nothing else gives you the whole package of performance, flexibility, maturity and monitoring.

> Aside from terrific performance, the JVM gives you the best concurrency platform out there (though not the easiest to use)

It's getting easier



I think clojure is also actor based.

In my opinion http://www.typesafe.com stack is the most powerful and consistent one running on JVM. Scala/Play/Akka/Slick/SBT speaks for itself and I enjoy every day of working with it.

Not sure if I enjoy SBT but Scala/Play/Akka is definitely great

Does anyone enjoy SBT? My love for Scala is profound, but fuck SBT

Yes, I enjoy SBT. I miss it every time I end up working with similar tools for other platforms.

I'm not crazy about the syntax and I avoid build.sbt files, but as a tool it's very pragmatic and takes care of my needs perfectly. It has incremental compilation and continous testing built in. For testing within SBT with something like say ScalaCheck simply works out of the box with no configuration necessary, by simply slapping a ScalaCheck test in the test directory. SBT has cross compilation support, something that is needed for Scala. Some of the best Maven plugins have been ported to it (I enjoy sbt-release for example). I tried my hand at writing a simple SBT plugin and it really isn't bad. Dependency management is based on Maven repositories, again something that I miss a lot on other platforms. Publishing stuff on Sonatype has been painless. SBT's support for sub-projects in the same repository worked flawlessly for me and it is easy to setup. The console support is great too, allowing one to easily open a Scala console with the right classpath loaded (compile/runtime versus test). And in general I like how it just works out of the box.

Every time I end up interacting with Python for example, I get headaches from the clusterfuck that is setuptools, easy_install, pip, wheels, virtualenv, virtualenvwrapper or whatever the fuck they are using these days. Every time I interact with Ruby, I get headaches from rake, gem and gemspecs, bundler, rbenv, rvm or whatever else they are doing these days. I don't even want to remember Javascript and the clusterfuck that is npm, bowler, brunch.io, grunt.js, closure, amd, commonjs, browserify or whatever else they are doing these days. Or about .NET that's still in the Ant/Delphi age with MSBuild.

For Scala, the only fair competition that SBT has is Maven. And the only (other) pragmatic build/packaging/dependency management tool that I used has been Clojure's Lein, but lein lacks for example the capability of keeping a JVM process loaded, so you suffer the startup time every time you invoke a command, plus it seemed weird that lein doesn't offer things like continous testing out of the box. And speaking of configuration formats, lein's profiles are simply confusing.

You don't have to use SBT if you don't like it. Maven works fine and SBT's secret sauce, which was the incremental compilation, has been extracted in project Zinc and so it now works with Maven. But I still prefer SBT over Maven and when switching to other platforms it now feels like going back to 1999.

Minor correction: SBT's dependency management is based on Ivy's not Maven's.

And for those working in Scala and building with Maven still, I second the recommendation to download & run Ivy, turn on the useZincCompiler option in maven-scala-plugin's configuration, and enjoy substantially faster build times (and automatically falling back to a normal build if Zinc isn't running). You don't even need to specify a scala home directory for Zinc like it claims; scala-maven-plugin will tell Zinc to use the Scala libs from your Maven repo.

You're right, I meant something else - publishing artifacts happens on Maven repositories, using a Maven POM file as descriptor (or indeed an Ivy file, but libraries are usually published Maven-style).

I like this a lot. Setting up your own Maven repository on your own server, that can be internal or whatever, can be as simple as setting up a server that serves static files and the publishing itself is just copying files by means of SFTP or whatever. The protocol for finding all the listed dependencies on that server is also simple, so in case of problems you can usually understand what's going on.

This is much saner than the alternatives I've encountered on other platforms.

This. One can dislike the syntax but SBT's advantage compared to most other tools is IT WORKS.

SBT, also known as Slow Build Tool in my office.

Once I got my head around it, I began liking it. If you're using Akka's clustering, SBT's multi-JVM testing is killer.

I hate it and minimize its use while using other build tools whenever I can (in the same project).

Clojure is not actor based but has some terrific primitives for concurrency

Quasar's Clojure API[1] gives you very Erlang-like Clojure actors.

[1]: https://github.com/puniverse/pulsar

Specifically, core.async brings Go-like goroutines (channels) to Clojure.

On the off chance that readers aren't aware, pron, the GP, is the author of Quasar.

The JVM has a couple of pretty significant problems when trying to work with functional-style languages. The biggest one is the way it deals with the stack: It's not in the heap, and it's pretty limited, so with something like scala, and more specifically with scalaz, you have to do some contortions to avoid overflows. 90% of usages of scalaz trampolines are nothing but ways to work around JVM limitations.

I'd argue that today, you are better off with the .NET VM, as far as features are concerned. But being stuck in windowsland is really a non-starter for all kinds of applications. I can send a major task that will take 400 computers for a week to Amazon if my code relies on the JVM. If I write it in .NET, not so much

The stack doesn't have to be in the heap to make things better for recursion* , the JVM just needs to support tail-call optimisation.

See my blog post: http://blog.richdougherty.com/2009/04/tail-calls-tailrec-and...

I'm excited to see tail-call optimisation ("proper tail calls") coming to JavaScript. Hopefully a bit of competition will encourage the JVM to clean up its act too.


(* Heap-allocated frames can help with other things though, e.g continuations.)

In Scala I work with self tail recursive functions all the time. Scala optimizes self tail recursive functions just fine, rewriting them as simple loops.

Yes you do have to use trampolines for mutual tail recursive function, because the JVM currently lacks support for it, however if you take a look at the Da Vinci sub-projects in OpenJDK, a prototype has been in the works for quite some time, led by none other than John Rose and given the attention that invokeDynamic is getting, I have no doubt that this will also happen on the JVM: http://openjdk.java.net/projects/mlvm/subprojects.html

Also, Scalaz great as it may be, it simply sucks in terms of the actual implementation, as it has loads of functionality that breaks when that shouldn't have been a possibility in the first place. Every time I happened to investigate issues related to Scalaz, I always ended up with a "WTF were they thinking" moment.

> I'd argue that today, you are better off with the .NET VM, as far as features are concerned.

That's bullshit. Speaking of tail calls optimizations, the bytecode available in .NET didn't even work at all on 64 bits .NET, prior to version 4.5 - that's right, before 4.5 the tailcall bytecode was considered more of a guideline. And Because C# doesn't use it, they never bothered to optimize it, so it has a pretty dramatic performance hit in comparison with normal function calls. And Mono probably doesn't do tailcalls properly even today, with F# being unusable on top of Mono for several years.

In terms of features - for example the CLR doesn't optimize virtual method calls. This is killing dynamic languages, or static languages that diverge from the C# OOP flavor in terms of polymorphism. IronRuby was never even close to what JRuby could do even when Microsoft was funding its development, simply by virtue of JRuby running on top of the JVM. And now ever since JDK 7 with invokeDynamic, the performance boost is so amazing at times compared to Ruby MRI, that people are running apps on top of JRuby for performance reasons ;-) The JVM for example can inline virtual method calls at runtime and can de-optimize those call sites in case invariants change or in case it notices that there are no performance benefits. This is something that really few other VMs can do.

invokeDynamic is amazing. It provides a way to override the default method resolution that the JVM does, while still benefiting from the same optimizations that the JVM does for normal method calls. It even has benefits for static languages such as Scala, for dealing with closures and Java 8 introduces a facility for initializing a value that can afterwards be treated as a constant, so there are big wins ahead for Scala in terms of performance for things like "lazy val", or structural/dynamic types and others.

Functional languages use a lot of persistent data-structures and persistent data-structures are by their nature wasteful in terms of short-term junk. You need a really good garbage collector to not suffer from this and the JVM really has the best garbage collectors available. You should see what it can do in a server-side environment with server instances being hit with thousands of reqs/sec per JVM process of real traffic. I have and it's freaking sweet.

Also, it's actually good that Java's generics aren't reified. Reification is only needed for languages like Java in which the type system sucks and stays in the way for more expressive/advanced type systems. Language implementers have to pull off a lot of tricks in order to work around CLR's reified generics. F# has 2 generics type systems in the same language, as Hindley-Milner can't be piggybacked on top of CLR's reified generics.

.NET still has some niceties, like stack-allocated value types, which is sweet if you want numbers that diverge from the standard primitives offered and to avoid boxing (and JRuby suffers a little because of this). But btw, here's another thing that the JVM can do - it can do escape analysis and for example it can decide to allocate certain short-lived objects straight on the stack if it sees that those objects don't escape their context.


Agreed, in fact what's surprising is that anyone thinks it's surprising that the JVM with its billions of man hours and primary usage in mission critical finance/banking/etc is anything but one of the most performant, scalable, robust, well-tooled platforms around.

>Aside from terrific performance, the JVM gives you the best concurrency platform out there (though not the easiest to use)

Though I'd probably still reserve that accolade for Erlang OTP/BEAM.

Though I'd probably still reserve that accolade for Erlang OTP/BEAM.

I would absolutely not. Erlang/OTP/BEAM might be the best distributed computing platform (though Akka is making huge inroads), but Erlang is actually a pretty terrible at single-box concurrency.

Erlang has one concurrency primitive - message passing. Which is great, but it's not always the right one.

Consider a a producer process which solves a PDE or does a big Bayesian computation (output is an Array[Float] or Array[Double]). You have consumer processes which read from the array and compute sums over subsets of the elements.

In Erlang you are just passing around copies of arrays. In the JVM, you'll probably have a single mutable array. You'll either wrap the appropriate calls in arr.synchronize {...}. Or you can use memory barriers and let the consumers freely read from the array, and invalidate their computation if the producer wrote to the array between the start and end of their read.

I've been using Java since the 90s. The JVM is a pretty solid piece of engineering, but your post is pretty heavily loaded with hyperbole. There are plenty of other excellent concurrency platforms for example Erlang, Go, even the. NET CLR.

Is there any chance you could briefly enumerate some of the things that make the JVM's approach to concurrency so strong? I'd be interested.

It's not the approach, but the capabilities:

1. State-of-the-art garbage collectors, which enable good implementations of lock-free data structures.

2. Excellent implementations of lock-free data structures (like ConcurrentLinkedQueue and ConcurrentSkipListMap) and other concurrent data structures (like ConcurrentHashMap).

3. A state-of-the-art work-stealing scheduler (ForkJoinPool), excellent for both parallelism (as used by Java 8's streams) and concurrency.

4. A cross-platform memory model specifying memory visibility across threads.

5. Access to CPU concurrency primitives like CAS and memory fences.

These building blocks are a great foundation for any concurrent application.

Thanks - I use Java all the time - but sometimes I find knowing which data structures to turn to in a given situation tough.

That's true for any language, and any platform. The language can't save you from having to, at some point, understand how to properly engineer software.

Grab a copy of "java concurrency in practice", it's my go-to book for when I've got a tricky concurrency problem to solve.

Could you please elaborate on #5? What you mean there is the fact that AtomicInteger implementation is actually using this primitives on your target platform, correct?

It's more than that. AtomicInteger's implementation uses JVM intrinsics which are calls to methods in the sun.misc.Unsafe class, that, when JITted, are replaced by a platform specific machine instruction (where available), such as CAS or a memory fence.

Do you have more info on the cleanup in Java 9? Will they remove some deprecated methods then?

This talk has some good (and official) information: http://parleys.com/play/52549d02e4b0a43ac12124be

How do deprecated methods affect you? Just curious. Maybe I'm missing something.

In my opinion, they don't. If you use an IDE like Eclipse where deprecated methods are clearly marked by a strikethrough and marked with a compiler warning, I don't see the big deal. And the bonus is that old code still compiles with new versions (and there is something to be said for backwards compatibility, a la "This presentation is not compatible with Keynote" discussion from a few days ago)

Methods are marked as deprecated when they're planned to be removed in the next version.

That's the story that gets told, but how often have they actually removed something after deprecating it? Does anybody have a single concrete example of a method that actually went away?


I don't believe they have ever removed a Class or method from the JDK... Thread still has all of those super-unsafe or non-implemented methods in it (see: stop(), destroy() etc.)

I think part of the reason for this ultra-conservative approach might be that alternate JVM implementations could in theory have well-implemented versions of deprecated methods such as the above-mentioned Thread ones.

No, they (Sun) could not care less for alternate JVM implementations. The reason for that ultra-conservative approach was that they were hell bent on keeping compatibility.

System.getenv was deprecated (in 1.1?), and then replaced with an implementation that threw UnsupportedOperationException (in 1.2?) because it was considered to be non-portable.

Later they saw sense and re-implemented it and un-deprecated it.

What is best practice when it comes to Java GUIs?

Would you recommend Java for building cross-platform desktop apps with near native UI performance?

The IntelliJ IDE looks great but most Java desktop apps I've come across just look and feel weird. Not sure why there is such a big difference.

You have probably encountered the occasional Java desktop app, without realising. If you can't easily tell it is Java, the development team have done a good job.

Two of my company's three products are a Java desktop app for Mac, and they look and feel like typical Mac apps.

Best practice? IMO you should spend significant time on the GUI making sure it feels native. Otherwise, Swing is still about as good as it gets for Java GUIs. JavaFX is supposed to be more modern and superior, but lacks the large-scale support and third-party component ecosystem that you find the Swing. Although I'd be mighty pleased to be proved wrong on that one!

>You have probably encountered the occasional Java desktop app, without realising. If you can't easily tell it is Java, the development team have done a good job.

I've never seen any Java desktop app that I cannot easily tell it's Java. With most of those apps, even on i7/16GB/SSD systems, you get laggy behavior with Swing and the GC. And SWT still has the "uncanny valley" look going.

Usually because the said developers are too dumb and do everything on the UI thread.

Yes. And things are a lot better now, I remember using IBM WebSphere UI tools (written in Java) circa 2004-5.

It took several seconds of whited-out buttons and stuck UI for every CPU intensive operation -- all on the same thread. And that was from IBM, and from tools that you paid for a small fortune.

Java as a desktop front-end language is dead. Sorry. JavaFX is a sad attempt at trying to re-live it, and no one outside of enterprise environments that are pure JVM shops are attempting to use it.

Actually, no, we have used it for a decade and continue to do so, because it is a reasonably clean and performant UI framework that gives us great control and pretty decent platform-native look and feel.

I challenge you to do anything that is first-class profession UI/UX experience in Java, and not want to tear your eyes out in the process. Try building something Aperture, Keynote, etc in Java. I don't know what you're building but my guess is it isn't 'beautiful' or innovative UI.

True, but how many of us programmers either want or need to do that? Less than 1% I'll bet. For the rest of us, Swing works just fine, and it's a whole lot better than some of the other UI toolkits out there.

Except basic interfaces can still be done with things like iOS. If you're going to take the time to build a UI framework, it shouldn't specialize in being craptaculuar.

I'd also venture to say a lot more than 1%. Modern world (finally) recognizes that design/experience are core to any product, enterprise or not. That's part of the reason there's a whole new breed of funded enterprise companies out there -- they're taking lessons from the web/apps and applying them to replace old-school solutions. [I'm personally hoping more people recognize this need for developer tools which typically are the worst offenders of all, particularly on the database side.]

Part of having a good framework is what allows apps/applications to excel -- it helps you raise your own bar because the tools are just so much better that nicer UI/UX can be had without being a nightmare in code. That's a win for everyone.

it's just pining for the fjords.

More seriously, as a recent example you will find that what bitcoin.org offers you as the first option for a wallet (multibit) is written in java.

That may not be mainstream, but it's definitely not the classic enterprise java shop.

And it looks like it was written in Java. Compare against any serious iOS app, for example.

I've been writing UI code for years, including in Java, .NET, Android/iOS, web, etc, so I have a pretty decent clue about building complex apps in all of these frameworks. Java just isn't a modern environment, and by being cross-platform you end up with an ugly lower common denominator that doesn't have useful APIs for non-trivial designs. iOS is probably the best framework/api out there and even that has many issues (luckily obj-c's categories help you fill in the holes).

JavaFX is now a default platform (supported by Oracle) for developing desktop apps. It replaced the clumsy Swing and is showing a lot of promise. http://www.oracle.com/technetwork/java/javase/overview/javaf...

How widely is this adopted? FX is one of those tools I'm a little leery of because of the possibility it may be abandoned by Oracle if not enough people use it.

What is the case for desktop apps these days vs web apps? I would love to mess around with JavaFX but really can't come up with a compelling reason to use it.

If you want to interact with local hardware/storage media, native apps are still easier. "Offline" mode can also be the default, at least for systems that have a local data store. Finally, multicore CPUs may be theoretically exploited with web workers, but it's a lot easier to just spin up a native thread in your Java code.

Downsides are all the usual ones, of course: updates don't happen automatically, you may need some sort of licensing/DRM if you want people to pay for your application, and your testing story is a lot more complex. (Plus: look-and-feel on various platforms, reverse engineering is that much easier, etc., etc.)

Offline + sync, and higher performance requirements are my two use-cases for desktop apps.

In theory, the Android runtime environment could be ported to most desktop environments. I have seen Dalvik running on Windows 7. I used to be CTO at a company that developed an Android runtime for WebOS. You might infer they could do the same for similar platforms. Jolla has demonstrated Myriad's similar technology running Android apps in Sailfish. So while there isn't as cleanly defined boundary between app runtime and OS as with JavaFX, which is designed to be cross-platform, in practice it is possible to move the Android runtime across platforms with good results. It should even be possible to put Android apps into realizable windows in desktop environments.

There is a lot to be said for taking an environment with a big following and making it cross-platform vs making a cross-platform environment and hoping for adoption.

Have a look at SWT. It's the best way to do Java UIs IMO. I don't know why it isn't more popular. It uses the native UI kits internally, so it feels and is 100% native.

There is more to a native ui (common spacing, font usage, interface patterns) than just swapping out the underlying widgets.

Exactly. Try using SWT to do anything like CoreAnimation on the mac with either similar programming ease or buttery results. There's a reason why one should go native for anything beyond a database viewer.

100% native on Windows maybe (and even there it depends on the Windows version). On the Mac it's like a foreign object.

And that's for the more basic widgets -- more advanced widgets have custom implementation from primitives in SWT, so they are hit and miss with regards to native look and feel.

You might be interested in Nifty: http://nifty-gui.lessvoid.com/

It's hardly any "best practice" or "standard", but it looks like people are managing to ship projects with it. Performance is reasonable; on the inside, it's openGL via lwjgl.

Another option is libGDX: http://libgdx.badlogicgames.com/

Their presentations appear to be oriented largely around games, but the parts could be used for a desktop application just as well. There's a number of mobile games in both the app stores using it.

I agree that the JVM is pretty awesome and will only improve (lots of money is bet on it after all) but I think BEAM may fulfil some of the items on your "awesome runtime" list :)

Applications are open for YC Winter 2018

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact