My apologies for this post being a little tangential.
My apologies for this post being a little tangential.
The JVM is an extremely fast platform given its feature set. It also has a coherent and powerful concurrency specification that is stable. While it is possible to have very low latency systems in Java, it requires a bit more work, and people tend to gravitate to C++ if the 3x penalty from C is too high.
But aside from the latency, if you can deal with full GCs, Java is a data throughput monster. The default GC is actually very good in most cases, and the JVM GCs allow significant performance tuning, which is a discipline in its own right.
It will be interesting if the low latency Z Garbage Collector introduced in JDK11 eventually removes one of the last complaints on Java performance.
Performance is.. complex. The lack of value types causes a lot more indirection, the hotspot compiler patches away some of it, the copy collector will compress connected objects together so that they will fit 'automagically' into CPU cache.
Unoptimized Java code may often run faster than unoptimized C/C++ code, but Java gives you only vague, global flags for attempting to tune memory behavior and code generation.
For monolithic Java applications, you can have a lot of different memory patterns internally (short term objects for the web stack, medium-term objects for transactional state, plus long-term objects representing accumulated state) which can really muck with the garbage collector's assumptions around generations. For server applications, this can cause things like heavy load causing request/response short-term state to be promoted to the mature generation. You start having to break up monolithic applications for performance reasons.
But, that still is being a victim of your success - and you would be better off by default creating the first version of your application in a language that allows your developers to iterate quickly.
Java is fast, has amazing IDE support, large library ecosystem and it's a solid language. And yes, I stand behind the last claim, I don't understand why Java gets so much hate. Swift is the best-designed general purpose language I've used and it's not hugely better than Java.
BTW, part of the decision to use Java was that I'm very familiar with it and wanted to get started fast, but now I'm having second thoughts. I guess Kotlin would be a good choice? And maybe Swift but not sure about library ecosystem on the server.
I remember when java first came out, I thought it would take over the world if they would "finish it". To me, this meant letting it run like other scripting languages:
#!/usr/bin/java
and let it do useful things everywhere in the os, but with wonderful OO.But instead of becoming a systems language, it sort of became a "nice cobol" that was mostly adopted to do business logic. I suspect the limitations imposed on it were to ensure portability and security, but it sort of polarized the people who would or would not adopt it. It was approachable to people who didn't think pointers were necessary (or some who couldn't do pointers), and repulsive to people who didn't want these constraints.
I think over the 20 or so years that followed, the idea of what java is used for has stuck. I also think perl took up the slack on the systems side, with python.
I wonder if java had been more of a systems language from the start, would it have been unsucessful? Or would it have displaced perl/python?
Now that I think about it, I can understand why people would dislike Java, the standard library kind of sucks, it lacked lambda functions before Java 8... and in general there seems to be lack of focus on usability and elegance, which also spreads to the ecosystem. Modern Java is not that bad though.
But - Java offers a surprisingly unique package - it's fast, it has GC, static typing, good library and IDE availability, supports both OOP and functional programming (kind of). There's really only 1 competitor unless I'm missing something - C#. There's also Kotlin if that counts. Swift doesn't have GC and not sure if it's mature enough outside of the Apple ecosystem. Dart is slower.
Ecosystem wise: - The JVM still uses quite a bit of memory, sometimes 3-4x more memory than say Ruby or Python (which are also garbage-collected languages). There is a reason that Android phones ship with several times more system RAM than iOS devices. - The JVM is gradually becoming only suitable for server development. Client GUI development has been mostly abandoned (with applets being deprecated, no Swing improvements for years, and JavaFX no longer being an official project), and the startup time is too slow for systems development a la shell scripts - IDE support is actually more middle-of-the-road in my experience. IDEs can suffer from needing plugins to deal with diverse third party tools such as build systems and test systems, often themselves developed with no regards for how to integrate within a graphical environment - Many popular libraries exist in varying states of disrepair. Lack of clear stewardship by Sun then Oracle caused several libraries to target quite ancient JVMs. - Use of popular libraries can thus hinder your ability to use newer JVM features, and can even hinder your ability to upgrade to newer JVM releases - exploratory and incremental development (REPL environments, exposing server app changes) have historically been pain points. I personally have seen environments where verifying a a fixed typo in a JSP template file requires a five minute redeployment. - there are some very poor programming patterns (such as getter/setters for internal state) which have been cemented in the Java ecosystem, such that I would never recommend it for starting or junior developers. - there is a long-standing reputation for java developers (more than developers in other languages) to treat Java as a hammer and all problems as a nail. In reality, Java is in the top ten for solving certain problems, and outside the top 50 for solving others. You simply can't be good at everything. But this means a lot of recommendations to use Java get discounted - "is this person only recommending to use Java because they have zero experience with anything else?"
The JVM and Java language themselves: - The language has gone years with relatively few improvements. - The language has a strong guideline of backward compatibility maintenance which hinders the efforts to improve it. As examples, lambda support was added in Java 8 without a clear model for dealing with errors, as well as Optional added without compiler support to enforce usage or VM-level support to optimize memory layout. - There is a lot of dead weight and known bad classes in the standard library (many pre-1.2 classes like Hashtable, two date/time systems, CORBA, RMI). Some of these are finally being removed from Java by being relegated to external libraries. - The language and JVM have an obfuscated generics system, with features (such as reified generics) likely never to be completed - The Java language is wordy and simplistic, requiring a lot of code to accomplish tasks compared to many other languages - Due in part to the simplicity of the Java language and focus on supporting multiple implementations of library APIs (such as multiple logging frameworks, multiple XML libraries, multiple JSON libraries, and so on) the language tends to be design-pattern-heavy and complex to navigate. - The exception model of Java (with checked exceptions) is generally considered to have been a poor choice now. - The class loader creates frustrating-to-diagnose issues, eating up valuable time you could be working on your application
Kotlin solves some of the language issues, but not the JVM or ecosystem issues.
Swift has a nicely developing server ecosystem, but does act differently from Java in important ways. Java has a broken intra-process isolation model, but you do still have web "containers" that allow for deployment/redeployment of applications on a running server, and which will attempt to recover gracefully from programmer errors. Many Java applications dedicate a thread for handling a request, and will handle exceptions as a failure in that request - but otherwise continue on attempting to handle future requests.
Swift is _not_ gracious about programmer errors, and will abort() on misuse such as force-unwrapping an optional without a value, or indexing an array beyond bounds. This is not unusual (node and PHP are examples of servers which will abort on certain issues) and is generally a benefit in that you get to diagnose failures by primary effects rather than secondary effects, but it does mean that you need infrastructure to catch such issues and make sure a new instance of your server is started.
(For what its worth, there have been proposals in the future (post a Swift language concurrency model) to add isolation around subprocess or actor boundaries, so that unexpected errors would only abort a "portion" of a server.)
The JVM will use as much memory it is assigned. Different GCs are more liberal with memory usage, especially the ones tuned for throughput. Newer, latency tuned GCs (like G1) will commit unused memory back to the OS.
The performance of Java is nowhere near as Python and Ruby. Furthermore, Java is used in memory constrained systems like blu ray players and chip readers. So it depends on the JVM implementation and tuning.
> There is a reason that Android phones ship with several times more system RAM than iOS devices. - The JVM is gradually becoming only suitable for server development.
Android is not a JVM implementation, so you cannot make this claim.
- Python is a pretty popular language for server development. It does have some performance issues (including a global interpreter lock), so you would have to decide the trade-off of your time vs infrastructure cost. - Ruby on Rails and Sinatra are both pretty mature at this point; less trendy but a known mix of positive/negative points. In particular, I have a pretty easy time making high-quality REST APIs and backing persistence store in rails than in a lot of other languages (but I'll also admit to a stigma against Python based on a prior work project I had to co-own and maintain) - Javascript (via Node) isn't to be flippantly discounted. It isn't the best language and doesn't have the best tooling, but for a web application you likely will have front-end javascript anyways. You can also use Typescript, which usually is a net positive for productivity and maintainability (but I've hit a lot of issues lately with third party library type definitions) - C# is becoming more compelling with the .Net Core work. In some ways it feels like a Java which was properly maintained by its vendor. - I won't bash PHP, since its disadvantages are well known. But for quick prototyping web applications (without excessive javascript), a dev with PHP experience can work faster than in just about anything else - For non-web applications, Erlang (or Elixir) as well as Go may be the best choices due to their inherent support for concurrency. I can't comment on their use for making web applications. - C and C++ win in terms of theoretical maximum throughput and lowest latency/memory usage - but it requires time, knowledge, and skill to achieve that, and you likely care much more about business logic. I've seen experienced developers work months on a C-based server, only to beat its performance with something they wrote in a weekend in another language. - Swift imho has yet to be proven for the server. If you love the language it may be worth trying for a project, but I wouldn't choose it for something on the critical path (yet)
Java still has huge benefits when integrating with third party technologies within a monolithic application. For example, when selling servers acting as on-premises middleware, Java enables you to use third party libraries and some glue code to make a plugin to theoretically support everything. You also have the benefit of being able to publish a programming API for others to extend your product themselves with Java code, something which may not be as easy to accomplish with compiled languages or if it requires the customer to learn something a bit more esoteric.
Java is somewhat unique in how easy it is to add third party code and dependencies to a project - scripting languages usually cannot match this as dependencies may also include native code. This is one area where Pure Java was a win, and is why a lot of distributed processing systems (such as Hadoop and Storm) often are written in and prefer Java.
Finally, I personally don't buy into JVM languages very much (Using JRuby/Jython to run portable code on the JVM is another matter). A different syntax doesn't solve the problems with the Java ecosystem or the JVM's resource usage or lack of inherent support for newer programming concepts. As soon as you branch out to use Java code, you lose a lot of the safety/immutability guarantees and features in the new compiler model. In return, you lose the ability for all of the Java developers to be able to understand and contribute to your code.
It's interesting to me that people don't seem to throw shade on C++ as much even though it's even older and in many ways harder to use effectively than Java.
I hear my friends make dismayed noises about C++ any time they are forced to work on it. When I look at Java or C# code snippets I mostly feel like I understand what's going on. C++ makes me go wat?! far too often.
Personal opinion I think Java would have a better rep if they'd optimized the GC for latency instead of speed. C# on the other hand would have a vastly better rep if it wasn't a Microsoft product.
Also despite the marketing hype the main application for Java was server side. I wouldn't be surprised if GC latency issues weren't a problem in that space.
Go does not scale well and it is a dumb language, not that that is bad. But just that it does not feel like a improvement to switch to Go.
Rust is still new and I think it will not get mass adoption like Java because of higher learning curve.
The rest of the differences are just having different standard libraries/tool chains. I don’t think that, for a novice knowing neither, rust is somehow much harder than c++
I think this argument only really applies to rust’s learning curve if one assumes that each year universities asses the programming language world for the best teaching languages and pick out those which can be used for the courses and are easiest to use. They obviously do not do this and you can tell because they picked c++ (which is actually at least three languages to learn with the preprocessor macros and the functional programming language that is hidden in the template system)
What do you mean? I've seen huge services built in Go handling an enormous amount of traffic.
(Disclosure: I work at Google, primarily in C++ and JS)
final var a = foo() ? bar() : baz();
Is several lines in golang, which doesn’t even have an analogy to ‘final’ var a int
if foo() {
a = bar()
} else {
a = baz()
}Are there any articles to back this up? I'm aware that the scheduler and networking integration are certainly opinionated. Nevertheless it seems to work very well for most applications that I have seen so far.
Also other things like you have to import “strings” to use features like split and substring, instead of them being defined on the string struct itself, which makes code awkward. No string interpolation which is quite ridiculous. The list goes on.
Additionally, a lot of the systems you mentioned can often benefit from the sophistacted dynamic classloader the JVM provides. For something like Spark (mentioning this one because I am familiar with it), it is a requirement to load and run user specified code dynamically. You can do this in C, but the JVM makes this much easier.
Then add in two decades of entrenched software and network effects.