Java 12(jdk.java.net) |
Even on the client where Java has lost to Javascript, I'm finding it more enjoyable to add features to my 15-year-old SWT app [0] rather than dealing with the multiple layers of abstractions that is Javascript+CSS+DOM (+ maybe Electron). Personally I think it's a shame Sun dropped the ball with client Java - if they had chosen SWT over Swing and provided a minimal JVM then maybe Java Web Start would have beaten Javascript web apps. It's also a shame Sun sold Java to Oracle - Google would have been a better steward, and probably would have been willing to pay more for the Java parts of Sun.
I'm now trying Dart to develop a few Flutter apps. It's no doubt a better language, but not that much better - I think Flutter would have been more successful if it was built on Java.
The flip side of Java's stability is stagnation. On the server-side, customers use mostly Spring/Spring Boot these days to make Java's overengineered stack usable, using even more over-engineering and metaprogramming. Same with maven/gradle, which turns what should be a developer-focussed build system into an enterprise XML mess.
SWT? I'm glad it works for you. Last I heard, IBM had pulled out of developing Eclipse and SWT/RCP over ten years ago. In the one project where we used it, the app looked like an IDE, and customers hated, then cancelled it. Designed as wrappers for OS-native GUI controls, it has even less of a place in a browser than Swing had. Last I looked, of the Java rich-client frameworks, only Swing has been updated with HIDPI support, whereas JavaFX and SWT haven't. None is using any of those (with the exception of experimental JFX apps) for new apps in this decade.
Whereas in the modern JS world, you start out with a lean project and then add small libraries from NPM that all work slightly different for every feature you need, in the Spring world where the framework has matured for 10+ years most of the things you will need are in the box or are available as external libraries that all work on the same defined interfaces.
Spring Boot with Java 11 or Kotlin are still my preferred backend stack for that reason. It’s solid, has aged well and makes me super productive.
Even stuff in “core” dependencies like webpack/yarn/npm/npx/nvm/babel changes a few times a year.
Right now doing a react native app and a browser extension. While javascript/typescript is fun to write, the time you have to spend fixing the tools is just horrible. Whiping cache, rebooting, switching package versions.. It makes the overall experience cumbersome.
I would not call something stable if it manages to work 2 whole years.
There was definitely an era of that, but over the past decade or so it's been acknowledged as a problem, and there's been a lot of effort put into making things simpler and more vanilla. Modern Spring is much much closer to plain old code. (Of course it's still possible to write in the XML/setter injection/afterPropertiesSet style, and always will be - that's backward compatibility for you - but it's very possible to migrate existing applications to a better style in place, which very few platforms manage).
> Same with maven/gradle, which turns what should be a developer-focussed build system into an enterprise XML mess.
Maven is pretty close to the perfect build system, it's just taken a while for knowledge and practices to catch up with it. All the stuff people love and praise Cargo for, Maven has been doing for 15+ years.
Despite Spring being Enterprise it still scales down to simpler apps pretty well due to its modularity.
These can be build into a single jar app that is easy to build and deploy, and combined with a database migration library, maintain their own database schemas. Very, very usable.
Yes, I probably would not use Java on the frontend unless it was for a technical audience.
People complain about the verbosity of Java, but how much time do you spend learning a new framework and all of the gotchas? At the end of the day it seems easier to just write the boilerplate. All of that verbose code means you got exactly what you asked for.
JVM projects never surprise me. When there is a problem debugging is a dream.
Could you elaborate on the overengineering part? There are many modern frameworks that are much lighterweight than Spring/Spring Boot, and with the introduction of lambdas in Java, things are even more straightforward.
Also, gradle doesn't use XML.
All our customers doing Java Web projects are either on JEE, or a CMS platform running on top of servlets and JEE related JSRs, like Liferay and AM.
I also do a good bit of frontend and holy crap it's exhausting. That's the main reason I push hard for Java backend. Backends tend to stick around about a decade longer than you would like, while front end code is due for a rewrite every 3 years
They didn't and Google didn't want a pay a single dollar to Sun on Java. As James Gosling has mentioned multiple times. I don't understand why people are still painting Google as Saint after all these years.
currently they recreated the java apis by pulling in apache harmony and they tought that they are in the right or at least in a fair use position (they still think they do). but I agree, I'm not sure if the direction of java would've been better when google would have the stewardship.
java is a stable api but it also doesn't evolve. The tradeoff is you get a program guaranteed to work no matter the upgrade vs being able to build better toolage.
React changes every year or 2. It is exhausting. But you get way better patterns and some things that drastically improve productivity.
Also keep in mind that React is a library, not a language. If you want to compare things, compare Javascript to Java, or the Java stdlibs to React. Maybe that's what you meant when you said Java.
IMO, Java and its libraries are nicer to work with solely due to its static nature and OO design. It is worlds apart from a scripting language when you need to refactor, or even just understand, legacy code. And if you can't even run tests on that legacy code anymore, like a React project over a year or two old?
What are the better patterns and productivity boosts you get from React vs. a Java ecosystem?
That and a few page reloads never killed anyone.
You have probably missed the last 5 years. From streams, to closures, to default methods, to functional interfaces, to local type inference, to new Process APIs, to modules, to unsigned arithmetic, to new date/time APIs, http client, 2 new GCs, shell REPL, etc... with more to come, and new releases every 3 months...
It consists of the main Flutter app and a Dart library for communicating with Nissan's API.
Maven and spring are the worst parts, for me, when dealing with Java. I don't mind the language at all.
Worse: Oracle bought Sun.
"Add a new garbage collection (GC) algorithm named Shenandoah which reduces GC pause times by doing evacuation work concurrently with the running Java threads. Pause times with Shenandoah are independent of heap size, meaning you will have the same consistent pause times whether your heap is 200 MB or 200 GB."
The original algorithm was published in 2016 [2]. It consists of 4 phases: initial marking, concurrent marking, final marking, and concurrent compaction.
But (in my naive opinion) double dispatch seems a more elegant and java-ry solution, i.e. polymorphism on argument classes, so different methods are invoked for different object runtime classes (instead of using the compiletime type of the variable).
The switching could be optimised, as ordinary polymorphism is in the JVM.
Sure, you'd wreck legacy code if you just introduced it, but there's surely a backcompatible way to do it that isn't too awkward.
BONUS: goodbye visitor pattern!
Sure, you could match on types, but you wouldn’t be able to extend that to destructuring patterns, or regsxps as patterns on strings, or so many other ways patterns may be extended in future releases.
Their initial motivating examples was bare instanceof, but I now see they extend it.
How would destructuring fit this model ?!
From what I understand, graal has made a lot of headway with language interop, as well as a handful of specific memory optimizations and native compilation, but overall is lagging in pure throughput/latency performance behind hotspot. It would be really cool if we could get the best of both worlds.
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
} System.out.println(switch(day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
}); int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};Actually, looking at the version history, I guess it's not weird that I thought 8 was pretty recent, as until 1.5 years ago (Sept '17) it was actually the latest and it is still supported until 2020 (unlike 9 and 10).
v6 2006
2007
2008
2009
2010
v7 2011
2012
2013
v8 2014
2015
2016
v9 2017
v10 2018
v11 2018 again
v12 2019I'll never know.
If they wanted to decouple, they first should have created a cross-platform jpackager-like tool that generates native executables for major platforms.
I remember JavaFX was launched with great fanfare as a modern replacement, which it certainly might have been - a modern, efficient platform. I am afraid it will slowly decay and dissolve into oblivion to be replaced by gigabyte-size electron apps.
Why? Besides being owned by Oracle, which is enough of a reason to never use Java ever again, it's also lost the niches that brought it into existence. Java no longer runs everywhere. Java on the web is dead, and you can now write ubiquitous apps in basically every language. There's no reason to deal with the JVM and it's domain knowledge when you can write a nimble Go app for your backend and a Javascript app that will run on mobile, web, or desktop. A VM language? You mean v8 sandboxing and web workers; WASM which lets me write C, C++, and Rust all of which can talk to Javascript APIs. All of my services are stateless and ephemeral. Crashing is expected, and I can use host monitoring tools instead of introspecting the JDK. On the cloud it gets even worse for Java. Why use a meaty framework like Spring when I want to just spin up a bunch of micro services, or have an API gateway kickoff a bunch of lambda jobs.
Java also took OO in so many terrible directions. OO defined by it's creator looks nothing like the enterprise OO that big business sold to commoditize programming, which now only exists as a ball and chain on legacy systems.
One day Java will be like Cobol. There's probably a lot of money for Java developers for many more decades, but god I do not envy anyone that has to do it.
That. I've used the Servlets API for years in the early to late 00s.
I'm now (for the past 5 years) using Express with Node.
Static typing and cosmetic differences aside, Servlets and Express (or Node's raw handlers) are pretty much the same API.
Request, Response objects, handlers, middleware (iirc we used to call those last "filters" in the Servlet era), etc. It's not like it's some alien convoluted design.
(Java Server Faces now was another thing)
GC use can be optimized in high level languages with support for value types (which are still missing in Java, though) and it is not like every game needs to be the next Fortnight.
There is such a thing as reference counting :)
(This is why I'm excited for ARC / Swift on the server...)
The performance increase is from a different algorithm + full multithreading. Not from collecting garbage less often as is a common tactic to reduce time spent in GC
"35C3 - Safe and Secure Drivers in High-Level Languages"
Each JVM implementation (Azul, IBM, OpenJDK, PTC, Aicas,...) has their own collection of GC algorithms.
And their behaviour depends pretty much on the application as well.
Well, one could build and run Shenandoah GC with JDK8 and JDK11. Ref: https://wiki.openjdk.java.net/display/shenandoah/Main#Main-B...
Here's a presentation on Shenandoah by one of the principal developers (focuses on the how): https://youtube.com/watch?v=4d9-FQZZoVA
Slides: https://christineflood.files.wordpress.com/2014/10/shenandoa...
Another presentation (focuses on the how, why, and when) at devoxx: https://www.youtube.com/watch?v=VCeHkcwfF9Q
Slides: https://shipilev.net/talks/devoxx-Nov2017-shenandoah.pdf
---
Tangent: Go GC (generational, non-copying, concurrent mark and concurrent sweep) and the improvements it saw from 1.5 -> 1.8 https://blog.golang.org/ismmkeynote
The mutator/pacer scheme, the tri-color mark scheme, using rw-barriers during the sweep phase are interesting to contrast between the two GCs.
If you want an order of magnitude jump in performance need to see if the IBM work on Scala Native version of Spark manifests.
The GC time is lower and multi-threaded but most importantly the "pause time" is low and nearly constant (based on root set size)
The old GC's all scaled pause time roughly linearly with heap size. Apps that created a lot of garbage would have all their threads yielded for large amounts of time.
Now, essentially, it doesn't matter how much garbage you create. This is awesome because you used to carefully watch how many allocations you made to avoid bad GC times. Now it doesn't matter. Make as much trash as you want and the GC will deal with it
I expect this needs to be taken with a chunk of salt, since a smaller heap can only require so much GC...
Pause times. Not GC times. Shenandoah pauses to scan the root set only. The size of the root set doesn't grow with the size of the heap.
You can have a large root set and a tiny heap, or a tiny root set and a massive heap. They're entirely independent.
As for GraalVM, I don't think it's meant to be mixed in with those 2 at all. From their website (https://www.graalvm.org/), it sounds to me as if it's a completely different project that shares none of the goals the other 2 JDKs have:
> GraalVM is a universal virtual machine for running applications written in JavaScript, Python, Ruby, R, JVM-based languages like Java, Scala, Kotlin, Clojure, and LLVM-based languages such as C and C++.
> GraalVM removes the isolation between programming languages and enables interoperability in a shared runtime. It can run either standalone or in the context of OpenJDK, Node.js, Oracle Database, or MySQL.
Twitter use Graal in production - I think it's about 13% faster for them on their real workloads. If you send a Tweet it's going through Graal.
GraalVM is... complicated. There are a few parts to it:
1) An advanced JIT compiler, written in Java, and distributed as ordinary maven/jar packages, etc. You can use it yourself if you want. Interestingly, this compiler package ("graal") can be used for the JVM itself, and it will be used to compile the Java code that is run by the JVM. The "JVMCI" feature allows you to plug third party compilers into the JVM and replace HotSpot, and Graal (the library) is such a replacement. You can use this compiler on ordinary OpenJDK 10+ with a special startup invocation.
2) Truffle, which is another library for writing programming language interpreters. It does a lot of magic to make them fast. It uses the graal JIT compiler to do this, so it depends on the previous library.
3) A bunch of programming language implementations under umbrella: Python, JS, etc. These are implemented using Truffle. By using Truffle, these language implementations magically share an object model (so they can interoperate), and they get a JIT compiler, based on Graal, for "free". This means the languages can interoperate and JIT together cleanly (the compiler can inline JavaScript into Ruby!)
4) If you use Graal as the JVMCI compiler (i.e. for your host Java code), and you use Truffle-based languages -- Graal can extend benefit #3 to the host Java code itself. This effectively means the JIT compiler can inline and optimize code across every language boundary.
5) SubstrateVM, which is is a tool to turn Java programs into native exe binaries. The intent is you use SVM on the programming language interpreters, to produce interpreter binaries that look "normal" to the user. These binaries are run on custom, non-JDK/HotSpot runtime. The Java code is not JITed, but interpreted code -- Ruby, Python, JS, etc -- is. (This means you have benefit #3, but not #4). SubstrateVM uses a custom generational garbage collector (written in Java!)
6) The "GraalVM distribution", from graalvm.org. This is a combination of all the above pieces together as a sanctioned package. This package uses JDK8 as the base virtual machine.
7) The GraalVM distribution comes in both a "community" and "commercial" edition, which do have technical/feature differences.
Here's the thing: you can use everything from 1-4 with an "ordinary" OpenJDK today if you know what you're doing, and you don't need a special JDK build. SubstrateVM might also be workable, but I don't know.
Points 6-7 actually mean that there is generally a difference between "GraalVM the platform" and "Graal the compiler". Notably, while OpenJDK no longer has feature gaps vs the commercial OracleJDK, GraalVM does, which I find a very weird choice on Oracle's behalf and unfortunate, but maybe it will change one day.
If you want to use one of the new low-latency garbage collectors (ZGC/Shenandoah) with Graal, I don't think that's possible as of right now: garbage collectors need to interface with the JIT compiler, but ZGC does not support the JVMCI interface (it will explode on startup), and Shenandoah doesn't either, I believe (but maybe this changed). This will almost certainly be fixed in the future, of course.
Rest assured progress is being made.
https://jdk.java.net/valhalla/
The engineering problem is that they want to keep old jars running on a world of value types.
I suspect I won't ever use value types in my code though unless it's drop in to refactor from AnyVal=>AnyRef (or w/e the java equiv is).
* Does accepting a value type parameter accept it by value or by ref? * How does this play with GC? Can I get dangling ref with value type? * How does value types play with inheritance e.g. will it be like c# and struct and they will be boxed any time treated as ref? * How safe will it be to convert a class from being value type based to Object (w/e AnyRef equiv is). Will I need to inspect all methods that deal it now?
This can probably just be resolved with a style guide like c++ can be mostly sane if you're starting a new project today with an aggressive style guide, but I just appreciated not think about this and just count on escape analysis + gc + hotspot tricks like monomorphize code paths with some counters to be good enough.
For example: https://rcoh.me/posts/cache-oblivious-datastructures/
Something like
@FunctionalInterface
interface Function<T, R, E extends Throwable> {
R apply(T t) throws E;
}During compilation, type parameters are erased. "T" becomes "Object"; "T extends Something" becomes "Something"; assignment becomes type conversion. But at the end it works correctly. If you try to make something that wouldn't survive the type parameter erasure -- such as having two methods with the same name, one of which accepts "List<String>" and another accepts "List<Integer>" as their input -- it will be a compile-time error, because you can't have two methods with the same name and the same parameter "List".
But imagine that you have a type "MyException" extending RuntimeException, and your code has "catch (MyException)". After compilation, this would become "catch (RuntimeException)", which is wrong, because it would also catch other RuntimeExceptions, and it is not supposed to. But if you make this construction a compile-time error, then... the whole thing becomes useless, because what's the point of having an exception type you cannot catch.
Makes HashMap computeIfAbsent much less useful than it should be. It's impossible to use a function in there that throws a checked exception (all I want is for the exception to propagate out of computeIfAbsent for the parent method to deal with).
Best option I've found is to wrap it in an unchecked exception, then unwrap it in the parent method, which is just .... yuck.
public static void main(String[] args) {
try {
sneakyThrow(new IOException("io"));
Test.<IOException>emulateThrows();
} catch (IOException e) {
e.printStackTrace();
}
}
static void sneakyThrow(Throwable e) {
Test.<RuntimeException>sneakyThrow2(e);
}
private static <E extends Throwable> void sneakyThrow2(Throwable e) throws E {
@SuppressWarnings("unchecked") E e1 = (E) e;
throw e1;
}
static <E extends Exception> void emulateThrows() throws E {
}[1]https://www.artima.com/intv/handcuffs.html [2]https://lrytz.github.io/pubsTalks/ the link to his thesis doesn't work anymore. I cherry pick some of it in my talk for a Scala meetup in Utrecht https://www.slideshare.net/yoozd/effect-systems-in-scala-bey...
But my favorite is abusing the language using Lombok SneakyThrows. It just feels dirty using it. In a good way.
Sometimes I wish Java had one too to complement Optional. I wonder what the argument against that is? Too much confusion with the existing Exception system?
Funny enough, Java 11 will be end of life the following year. It's not even worth migrating to, better jump to java 15 then.
More importantly, the JVM ecosystem is much bigger than Java itself. The JVM is a highly-optimized, cross-platform, garbage-collected environment on which people have built much more progressive languages that lack the syntactic baggage of Java: Scala, Groovy, Clojure, Kotlin. Clojure is one of the most popular and performant Lisps we currently have, and Scala is one of the closest things we'll get any time soon to a practical version of Haskell. Both of these projects got to avoid building their own garbage collectors, which is an enormous lowering of the effort barrier. And to top it all off, all of these languages' binaries are interoperable, which not only allows you to use different ones for different parts of the same system, but makes it much easier to gradually migrate your legacy codebase to a newer, better language.
I don't know if I'd start a new project in Java-the-language, but it's far from a Cobol situation.
Apache Groovy has inherited all of the syntax of Java. When Jeremy Rayner built the Antlr 2 based syntax for Groovy back in 2005, he began with the syntax for Java, then added the Groovy-specific grammar to it. The latest version of Groovy still uses that syntax, so if Java has syntactic baggage, then Groovy has it too.
I'm picking Groovy will still have that baggage-laden syntax for a while yet. 2 yrs ago, Daniel Sun built an Antlr 4 based replacement grammar, but the Groovy project managers at Apache are taking their sweet time in rolling it along. They even had its optional preview removed from the version 2.6 beta of Groovy.
A lot of my reasoning was criticizing the JVM itself, not Java. VM languages add unnecessary complexity in the post container world where ephemerality and kernel APIs (containers) can give the same advantages, although I think Kotlin and Clojure and remarkably good languages.
Java is old, it's crufty. Yes.
But it's extremely fast compared to anything but Go, C#, and "low level" languages nobody wants to touch for web stuff.
The JVM is also extremely reliable. I've seen apps run for years straight.
And the tooling is better than basically anything. Profiling, debugging, realtime code generation and modification. Libraries for anything you can imagine. ~4 solid IDE's.
Java's OO is fine, and all the nightmare patterns died years ago. You only see them because Java has been around for so long. Modern frameworks like Vert.X or DropWizard are fairly nice to work with. Even Spring Boot isn't too bad.
But Spring is dated and not often used for new projects.
The JVM has extremely powerful built in monitoring API's that put any other language I know of to shame.
WebWorkers are trash compared to Java's nice threading model. It even supports CPU optimized Atomics.
There's nothing unusual about writing microservices in Java. V8/Node is just as "big" a virtual machine as the JVM except JS runs ~5x slower and takes 5x more ram.
You can also write Lamda in Java.
There's many valid critisicms of Java but yours are largely invalid
Yes there are.
...but the parent assertion that Java will one day be like cobol; no longer taught in intro to CS course (where now we see python), considered bloated and legacy, and not picked for new projects (where we see the rise of languages like kotlin eating into what was once the primary growth for the language with mobile apps) and encumbered by problematic licensing issues...
Seems quite valid.
You have to live in a bubble right now not to get the feeling Java is stumbling, and there’s no indication to me that the overall direction of the language is positive right now.
...I’m sure there are still years ahead for earning a good living as a java developer, don’t get me wrong, but that’s a different issue.
> But Spring is dated and not often used for new projects.
Spring Initialzr (https://start.spring.io) is used millions of times per year.
Fast is a poor word to talk about benchmarks between languages. Memory, throughput, latency are the things we should be talking about. There’s also trade offs where predictable scaling of latency under massive load is important (Erlang, Elxir), or spending less memory and starting up quickly in order to scale horizontally is important (Golang), or speed of development is important (PHP, Python), or correctness is important (Haskell, Rust). Java is rarely the winner in any area in favor of being well rounded, but as we should be using tools that meet at least the broad requirements it is always possible to make a better choice than Java.
> I’ve seen apps run for years straight.
This is why Java is dated. I am an Erlang developer, which is known for being hot reloadable and running forever. It turns out this model is actually juxitposed to Kubernetes and severless, which both presuppose letting processed crash at the host level and starting and stopping quickly. This also gets into the tooling argument because profiling in Java would rather the VM be long lived.
> The tooling.
I too have an operating system with great tooling, it’s called Linux. My knowledge of tooling is more broadly applicable, I can introspect any binary and attach probes to the kernel with bpf. Profiling for a VM is table stakes because you’re on your own. Not only do you have to figure out what’s going on in the JVM you also need to duplicate your effort to figure out how the JVM is running on the host.
> Java OO is fine.
OO in general is not fine.
- fast enough for most things without a lot of pitfalls/gotchas
- easy enough to read for most developers
- easy enough for most developers to pick up if they've never used it, even if they aren't exactly enthused by the idea of doing so
- supported enough that you'll never be the only person who is debugging something
- widely used enough to never be alone when you are trying to use it in unsupported ways
- has commercial support from multiple companies
Basically all the things that a lot of "enterprise" companies love.
Edit: formatting
Yes.
There is no need to engage the GP - let him rant about Go and JS. Java is still huge, for both legacy and new projects.
For context - I started as a C/Kernel dev. I also spent 2 years with Java on mission critical backend code. Both have their uses.
Applets, JavaBeans, and CORBA. What a loss.
> Besides being owned by Oracle, which is enough of a reason to never use Java ever again,
That stopped being an issue years ago. OpenJDK is a thing, you know?
> Java on the web is dead,
I don't think you have any idea about the hundreds of millions of lines of Java that power the web as you know it today.
The rest of your post is filled with equally uninformed claims but I'm going to stop here.
>> I don't think you have any idea about the hundreds of millions of lines of Java that power the web as you know it today.
Presumably they meant Java in the client, not the server.
Well, that's seeing the glass half full.
OpenJDK was complete garbage in the java 6-7 era, less than 5 years ago. Pretty much every major java software was requiring to install the Oracle JDK. Nobody would accept a bug or a support issue if it happened with the OpenJDK, which was the first question to be asked. And that wasn't fear mongering, java applications that worked perfectly fine just didn't work on the OpenJDK.
It is better now. I personally haven't seen an OpenJDK JVM crash in a while.
If Oracle's ridiculous interpretation of API copyrights holds up, they have a kill switch for OpenJDK.
Yes, Oracle, the company that sues people for breathing the same air owning Java is an issue.
Maybe I am uninformed, but you haven't made a good case that there's any truth to that.
The only reasonable alternative is C#. But it has to go a long way to reach Java's level of stability and trust on non-Windows servers.
> JavaScript itself is a terrible language (along with other dynamic languages like PHP, Python, Perl, Ruby)
You know, I used to think that languages had a single axis of Good. And each language sat at a certain point in that one dimension.
After several years each of experience writing large web applications using C++, Java, C#, JS, Python, Ruby and Go, that mental model of languages being good, bad or terrible seems incredibly naive now.
But overall, if someone were to ask me to write a web app today, I would probably use Python server-side and break it down into microservices. Client-side, probably just pure js + HTML5 APIs.
Why? Because I don't have the time to argue about languages being better or worse. I am too busy writing code that does useful things.
In a high-skill rockstar team, dev time is by far the most expensive resource. In a startup environment, using your dev time wisely is the difference between a unicorn and a failed business. Nobody gives a fuck if your route handler executes in 1ms or 20ms. I'll gladly pay the 20x hosting costs if that will get my feature out to customers a week earlier.
i don't know why this comment was downvoted so much. i fully agree with every point that LASR makes. if you disagree, i'd like to see your counterpoints please.
For browser or Node.js, TypeScript is the way to go IMHO. Node.js and it's ecosystem have it's issues, but TypeScript is quite nice and a considerable improvement over JavaScript, while being close enough to JS where it fits nicely into the ecosystem. Only downside is that it adds a compile step that can potentially grow to be time-consuming.
I feel bad for people trying to write in other languages and manually re-inventing dozens of features the JVM ecosystem just gives you for free. In many ways, the whole container-push has been essentially people trying to achieve what the JVM already gave you (isolation, cross platform, etc etc). I still don't see anything equivalent that doesn't impose huge burdens of complexity (which java does have but it's a known quantity with two decades of maturity).
Google did containers in Borg many years ago, and many of its servers are written in Java.
When I stopped caring about POSIX.
It is true that for smaller, less demanding software, there are many alternatives, but except for a very short period (~2000-2005) Java never dominated that kind of software. Early on people used VB, FoxPro and Delphi for that stuff, and later PHP, Python and Node.
Even with Rust, Go, and .Net core out there it's really hard to beat Java's battletested libraries/frameworks and excellent tooling. Java is still very relevent today and will probably still be for a very long time.
Also, funcitonal programming is a style of programming, not a collection of features. Just because you have a map and sort method and a hacked in lambda syntax doesn't make Java anything less than OO. Multi-Paradigm usually means one paradigm with a bunch of extra crap in there to make bike shedding easier.
Part of the reason big businesses were able to abuse enterprises with their abominable Java server stacks is because corporations were slow to trust open source. But developers persisted and open source became too compelling to ignore, creating the upward pressure to embrace it and break the bloated and overpriced enterprise app server's stranglehold. This likely prevented the demise of Java that you suggest has happened.
In fact, when it comes to enterprise these days, you're pretty much either a Java or a .NET shop.
You'd rather use wasm to write c to talk to javascript apis? Your case against Java might be more compelling if it wasn't so gross itself.
I still use Java a lot for application servers[1] and enjoy it.
I've also used Go, but I wouldn't want to try and implement, say a non trivial REST server with it.
I don't have the time to code everything from scratch, or to use an immature Go library or framework for example, when there are perfectly good ones in the Java world.[2]
Perhaps it might be best to just see languages as tools, and that each language has a purpose.
Java is old, so what? Lots of people derive value from it, and it's very stable.
You might be glad that banks use it, instead of immediately jumping on whatever languages you mentioned above. At least it manages to do boring things like keep you accounts relatively safe from hackers.
[1] https://www.dropwizard.io/1.3.9/docs/
[2] And yes, for that kind of application, unchecked exceptions are way more convenient than thousands of lines of if err != nil all over the place. And annotations in Go are an afterthought and it shows.
I'd suggest updating your misconceptions regarding Java before posting Yet Another Tirade about it.
E.g. the Javascript module/npm ecosystem is an absolute mess compared to any sane package/project description system, yet few people would disqualify JS for it.
Yeah, those poor devs with a rock solid, best of class, platform to write code on, with tons of libraries and tooling.
>Java no longer runs everywhere
It still runs everywhere where it matters. Nobody really cared if it could run on crappy smart tvs and other such BS SUN tried to push it. 99% of Java use has been for server work and enterprise development, and it remains there.
And on mobile, well, Android uses basically Java with a name-change.
>Java on the web is dead
Java on the web (Applets) was DOA, and has been dead for over 15 years. It's not gonna make any difference now.
>and you can now write ubiquitous apps in basically every language
Which again is neither here, nor there. People have been using Java as a very strong language for backend systems, application server side work, and enterprise stuff. And those deploy on at most one OS 99% of the time.
They don't use Java like e.g. Electron or QT. The only Java apps that are like that and are mainstream are basically IDEs.
>There's no reason to deal with the JVM and it's domain knowledge when you can write a nimble Go app for your backend and a Javascript app that will run on mobile, web, or desktop
Whatever.
>A VM language? You mean v8 sandboxing and web workers; WASM which lets me write C, C++, and Rust all of which can talk to Javascript APIs
How hipster. Meanwhile others do real work on Java, with finetuned GCs, mature libraries, and so on. I'm not sure where you've seen all this "WASM and Rust", as both are not even blips in production compared to Java adoption -- and wont be for a while, if ever.
>All of my services are stateless and ephemeral
Mine don't care much for the latest fads, so there's that.
>On the cloud it gets even worse for Java. Why use a meaty framework like Swing when I want to just spin up a bunch of micro services, or have an API gateway kickoff a bunch of lambda jobs.
I'm not ever sure what Swing has to do with a Cloud java deployment. Perhaps you meant Spring, but even so, it doesn't make sense.
And of course with Java you can always use something like Vert.x, which tops the performance charts for microservice work -- so much so, that the others are not even on the radar.
>Java also took OO in so many terrible directions.
2010 called, they want their arguments back.
Also, not sure if you've noticed, but Java is still in the top 3 of most in demand languages (along with JS and Python).
Perhaps your ideas about its death are premature, if not deluded?
You have me convinced.
And from this it seems to me you are somehow biased against the java ecosystem without hands-on experience to base your opinions on.
Java basically copied (and cleaned up a bit) C++ OOP of the time. Don't blame Java for any bad direction, it was following rather than leading.
There are also thousands of companies which are focused on Java, Java, and more Java. Many schools are also geared towards churning out more Java engineers, and people who don't yet know Java want to learn it because there are still so many Java jobs around.
That's a lot of inertia to overcome.
It's still true, though, but it's a compliment. Most languages have no hope of ever becoming the next COBOL. For Java, it is practically a certainty, even if Oracle were to pull the plug on it this very moment. It's too big and too important to die.
However I really dont see what benefits Spring brings. Spring Boot is great for prototyping and trivial apps, but for big systems you really want to break it apart. DI is better done with ServiceLocators. Some of the smaller libraries like Spring Shell, Spring Mobile are junk. And I still see lots of XML config that you dont know if they'll fail until you try to run them.
Will be interesting to see if ARC gets optimized for use cases like this (drivers). I wouldn’t say it’s super representative of general server programming though. And unless I missed it I don’t think they compared memory footprint.
Working with result types is really cumbersome in languages that don't have HKT (Rust hacks around it with a special-purpose language feature), and even more so in languages that also don't have pattern-matching. So I'm not sure how much use it would be in practice. But yeah it's the right way to solve the problem.
https://www.youtube.com/watch?v=ZYw3X4RZv6Y&feature=youtu.be...
or, they are more concerned with shiny new tech rather than using a mature and well-tooled out stack that doesn't sound sexy. I for one, don't need sexy tech - i want my app's domain to be the shining star, not the tech stack.
(And of course you skipped all the non-whatever points where you didn't have anything to respond).
I thought I had missed something there, but it looks like it's just a bunch of utility methods to reinterpret integers and convert them to longs (etc.)?
Kotlin, on the other hand, recently added actual unsigned types[0] – taking up the same number of bits as the corresponding signed type, supporting the normal mathematical operators, and preventing unintended mixups with signed types.
[0] https://kotlinlang.org/docs/reference/basic-types.html#unsig...
Yes, but it's also a new feature (along with dozens of others). The complaint I answered was that Java is stagnant somehow, when it has been evolving fast in the last 5 years, and is accelerating its pace (release cadenze) even more.
>Kotlin, on the other hand, recently added actual unsigned types[0] – taking up the same number of bits as the corresponding signed type, supporting the normal mathematical operators, and preventing unintended mixups with signed types.
Which, given that the JVM doesn't support them at the bytecode level (iirc), they also use some similar trick of working with signed numbers under the hood, just hide it better at the syntax level.
Isn't OpenJDK providing updates for Java 8 through to September 2023? 8u202 is published ...
And if it does, making themselved acquainted with how value types, slices and gc-free pointers work would probably be a better idea.
That also includes generic catch clauses and inner exception types of classes with type parameters.
In 2006 I played around with Jackrabbit for an architecture concept (for managing airworthiness of airplanes and kit). That was before the Iphone even existed. I was honestly surprised Adobe is still using it in their AEM product. From what I recall, it manages a document tree, based on a 2004-ish, Drupal-like node graph in typical Java enterprise fashion.
I'm no insider, but my guess is Adobe is struggling for some time now to integrate AEM, Magento, and other purchases into a lineup for creating shopping experiences. We'll see how this works out.
Not any more than PEPs are.
I have learned it pays off longterm to watch caravans pass by.
Pure HTML and CSS with minimal JavaScript rules rendering performance.
Lets see where it stands 5 years from now, specially if Fuchsia actually gets released.
Also, Kotlin/Native is in beta now and could target Fuchsia (compiling AOT to native code using LLVM).
Kotlin has IntelliJ (and thus a great IDE) and Google standing behind it, and Steve Yegge's nod of approval.
Thanks, looking it ip
https://www.reddit.com/r/FortNiteBR/comments/7gu8aq/hitching...
Thanks for pointing it out though.
Follow the conventions and it is less than a screenful for a basic project.
I typically solved maven problems by removing cruft and falling back to the standards.
I don't know what it is. I think part of it is my auto-cringe when I see XML nowadays.
Stuff like lambdas take extra memory, because they convert into anonymous innerclasses instead of invokedynamic.
Until it doesn't, then everything goes to Hell very quickly.
Spring is close to impossible to debug, because everything is driven by annotations, configuration settings, property files, beans defined in XML, default values, or code that runs because you added a dependency even though you never explicitly call it.
Program logic is defined in anything and everything, except actual Java code.
The whole thing is a nightmare ignoring every principle of simplicity, composability, referential transparency, and every other established principle of good software design.
I see a comment like this every week on HN and I've been meaning to write a blogpost or two to address this.
Yes, as you mentioned there is a myriad of ways to configure a Spring(Boot) application, and I think that is one of things that make it such a powerful framework or platform to build a service on. To address a few of your points:
* beans defined in XML : we don't do that anymore since annotations got introduced. I haven't written a beans.xml file in years.
* Program logic is exactly where you expect it: in the Java code. All the property files and annotations are used for configuration to allow for different environments. This setup allows us to run the exact same binary jar or docker image built from CI to run in CI, in dev, in staging and in multiple different production environments.
* configuration settings and property files are the same thing as the configuration values go into property files, you can have multiple property files to group configuration logically by their purpose, and if needed duplicate each property file per environment to group those together. I know my database config for the staging environment is in database-staging.properties. If that is not enough you can easily override any of the values with environment variables
* Debugging : another point where Java gets huge flak here on HN is huge stack traces, well I think those are actually helpful in figuring out exactly what is running and giving you trouble in a specific environment. And because of the separation of configuration from code mentioned above it is trivial to setup a testcase with the exact same configuration that you are having trouble with and use a debugger on that testcase to inspect and debug.
* Simplicity and composability : While the framework can look complex if you don't understand the configuration system, it is actually there to facilitate composability. See my point about running the same binary in all environments. The big idea is that you put all code in the same repo and then compose and configure your application at runtime with the configuration system.
But how do you even know what code to read when so much of the program's logic is in annotations and other kinds of action at a distance?
https://wiki.openjdk.java.net/display/shenandoah/Main#Main-F...
> Usual latency induced: >100 ms, but can be more, especially on a very occupied heap
Seems like it confirms precisely what I wrote? You can get longer pauses the less memory you have left, i.e. the more of the heap you've used...
Was there ever a MacBook with USB-B?
java.util.Date is bad, but it's not getting removed. java.net.URLEncoder is bad, but it's not getting removed.
var foo = new Map<String, String>();
The static initialisation methods on collections[2] let you write var foo = List.of(1, 2, 3);
It's still clunkier than many newer languages but it is improving.1. https://developer.oracle.com/java/jdk-10-local-variable-type...
2. https://docs.oracle.com/javase/9/docs/api/java/util/List.htm...
Nullaway and a bunch of other linters will also save you from accidentally falling in one of the dusty corners.
RxJava and Java Streams are also very nice.
Anonymous classes are nice too I guess (although they're fairly limited).
Overall the java experience has improved massively in the last 5 years, but you need to know where to look. Highly recommend the two popular "awesome java" repos on GitHub for an overview
The major point of JavaFX is cross platform development. Please offer a cross-platform jpackager, and we'll be happy.
The meetup was recorded[2]. I can't tell you how far through he mentions it, but its a good talk to watch as he goes into some of their rationale for their approach.
[1] https://www.meetup.com/Londonjavacommunity/events/258987722/ [2] https://www.youtube.com/watch?v=RWpo92OBaNA
They can be worked around by adding exceptions to removal of reflection metadata largely. Kinda a PITA but not too hard.
Active libraries have pretty good Java 11 support these days though. It's really improved a lot on the past year or two
So my upgrade is going to be tremendously hard for this application, then. Good to know
Basically a compile run fix reflection loop until you stop getting errors :'(
To Java 11 you might have additional hiccups when using JavaFX, or the JEE libraries that were also being bundled with the Java SE.
Which wasn't our case.
I’m not sure what would happen if values landed in 18, it might be an important enough change for people to want break the LTS cadence.
Do you want to optimise pause times? Use X. Optimise throughput without regard to pause times? Use Y. Optimise memory use? Use Z.
It may not be accurate in every case (no guideline is), but it would be a good starting point for the vast majority of us who don't know the pros and cons of various collectors.
https://docs.oracle.com/javase/10/gctuning/introduction-garb...
https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/gen...
https://www.infoq.com/articles/G1-One-Garbage-Collector-To-R...
https://www.infoq.com/articles/tuning-tips-G1-GC
https://developer.ibm.com/articles/garbage-collection-tradeo...
https://www-01.ibm.com/support/docview.wss?uid=swg27013824&a...
I use all those languages too. Use the right tool for the job. Don't be dogmatic. And don't disparage others.
Would I start a new project in Java? Probably not. But I might reach for other jvm languages that were mentioned elsewhere. I'm definitely not too cool to work on an existing Java project. It's fine.
However, I don't want to sound too negative. I can see a perspective for the JVM (Graal/Truffle) as a polyglot runtime where most of the ancient Java stuff is hidden from you, and you're using JavaScript or other non-JVM-only language as a migration strategy to get rid of Java alltogether in the distant future.
Could you be a bit more concrete? I don't recognize any of your descriptions in my experience of maven.
There are probably some bad plugins out there, but as in any system the solution is not to use them.
The complete lifecycle is listed in the documentation, and it's all very common-sense.
pom.xml isn't meant to be Turing-complete, and if you try to use it like a Turing-complete build language you will get yourself in trouble (as many of the early Ant diehards did). You need to treat it as a declarative config file, no different from e.g. Cargo.toml.
> I just don't have the patience with wading through crap that 2003ish Java nerds thought would be a good idea. And increasingly, as Java libs get EOLd, this will be a major problem for monolithic Java apps with tens of submodules. I don't think you can expect younger devs to keep maintaining daddy-o's web framework crap and cleanup the mess left by Java heads.
It's just the opposite. I don't expect anyone to want to maintain Ant or Gradle builds in the future, since they can have any kind of crap in them. But Maven builds are forced to be kept sensible; the tool just isn't flexible enough to let you put crap in your build definition, by design. (If you really insist on doing crap you can make a crappy plugin, but your plugin is then forced to be versioned, tagged in VCS etc., so stands a better chance of being picked up by your organisation's normal code quality efforts).
Modern Spring, as far as I can tell, is still very much driven outside of Java code, it's just migrated from XML to annotations and yaml properties files. Seems almost like the typical Spring application has more lines of annotations and properties files than lines of Java code.
I am fond of Maven, though, especially with Gradle (superior to pom files).
Disagree; there's been a shift to using constructor injection over setter injection, which often obviates the need for Spring-specific lifecycle methods. So it's now much more common to have a service class that, while it may have Spring annotations on its constructor, can also be used in a first-class way in plain old Java, and e.g. doesn't use Spring for unit tests. If you're using Spring at all then part of your application wiring lives outside Java code almost by definition, but it's now more common to express wiring logic as e.g. an annotated Java method rather than encoded into XML. It's not a complete departure, and it may not go as far as you or I would like, but I do think there's been a real cultural shift.
> especially with Gradle (superior to pom files).
It really isn't. Arbitrary unmanaged code in the build definition is great for writing but terrible for maintainability.
And historically, nobody cared for that style of programming in its pure form (where "nobody" is in the casual sense: a few FP-lovers, but not the 95% of working programmers).
From 1960 to today it remains niche in its pure form, even the most popular language following it fully (e.g. Clojure or similar) is still a niche language.
We found out, on the other hand, that people care for mixing that style of programming with OO, imperative, reactive, and other styles.
And that's what modern JS, Java, C#, Rust, etc (even C++) give us.
And since FP is a style, it can be followed quite effectively in almost any language -- as long as it has some basic features, which, as you observed, Java has added.
It's not black and white. FP is more like a spectrum, with pure functional programming more towards the opposite end, just before total functional programming. Put another way, adding lambdas to Java does not make it like Haskell. Even Scala cannot effectively be used as Haskell substitute, as some in that community eventually realised.
It remains to be see how much of FPs benefits (composition, abstraction, reasoning) can be fully realised in languages with rampant side-effects and mutation.
> We found out, on the other hand, that people care for mixing that style of programming with OO, imperative, reactive, and other styles.
Which is why you forgot to mention Scala, which shows us how great such a promise land can be when we try to please everyone.
> JS, Java, C#, Rust, etc (even C++) give us.
Out of the languages you mentioned, only certain circles of Javascript (React) and Rust are arguably functional as I mentioned above. Javascript has been a real exception to the rule in how its lack of real class support left a vacuum for some FP. C++, C#, Java, and the majority of Javascript are object oriented and always will be.
No, I think they are using those terms correctly. In FP, “pure” means absolutely no side-effects. So if you add an FP-style library to an existing imperative language, that’s “impure”.
I categorically disagree. Nearly any program has pieces that benefit from OOP and pieces that benefit from FP and everything in-between. The most prevalent and useful languages support multiple paradigms (C++ is a mess for other reasons).
C# as a language does tend to be nicer than Java, but its VM doesn't have as rich a family of languages.
Also, CLR has F#, which I like much better than Scala (and, no type erasure in CLR), Clojure which is ... just like Clojure on JVM, and C#, which as a Java dev since 1.1 I have come to prefer as a language even as I remain JVM ecosystem preferring on the server side. JVM has ABCL, a neat Common Lisp, and now Graal/Truffle which is super interesting. If not for Clojure though (and maybe Kotlin) I would probably give up on the JVM. Oracle does not help. Just my opinion.
But I disagree that Java is like Cobol. The syntax and general situation is extremely similar to C++. There's still tons of work being done on it, but it's a mature language that will be around for decades. IMO it's still the best language to run on the server for a multitude of reasons.
> beans defined in XML : we don't do that anymore But you still can do that! Also you still can do DI with Autowired private fields instead of injecting via constructors. You can also create beans based on properties. You can also create beans automatically via a included JAR on your class path. On Spring Boot you can also have beans created based based on some conditional annotation. And now there's yet another new DSL [1] to create your beans programatically on startup time. Tracking down and debugging what's loaded in Spring is super hard compared to Guice for example.
Configuration is another piece of software that I have a really hard time to think why they do that. You can configure via a YAML file, AND via a properties file, AND overriding via environment variables, AND also with a configuration server that store your properties on a separated server, and they are all mixed together in a weird single configuration entry for the specific environment that you have. Probably this made sense some 10 years ago when we loved J2EE but why support this kind of madness nowadays?
What I feel Spring is missing so much is forgetting about all the past and where the framework came from, start from scratch with simple premises around reactor-netty [2], only supporting the functional DSL, no crazy class path scanning, no crazy configuration loading, just a simple DI framework with some batteries included.
[1] https://spring.io/blog/2017/08/01/spring-framework-5-kotlin-... [2] https://github.com/reactor/reactor-netty
Non-trivial reference counting starts to look like mark-and-sweep GC.
And even then, when a ref count drops to zero, the runtime cost of destruction and deallocation of particular objects can be expensive. Stop-the-world GC is bad, but “make a blocking call because you can’t use async APIs in destructors” is worse - especially when the destructor runs in a program thread instead of a GC thread.
I feel that languages which provide support for defined object ownership and lifetime (Rust, any others?) will become the future because in many scenarios object-lifetime can be nailed-down by the compiler and thus eliminate the need for GC or ARC.
But yes, it's malloc and free.
[1]: https://www.cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
Go and C# running circles around Swift.
"35C3 - Safe and Secure Drivers in High-Level Languages"
https://www.youtube.com/watch?v=aSuRyLBrXgI
Possible stack overflows and unexpected pauses due to heavily nested data structures.
"CppCon 2016: Herb Sutter “Leak-Freedom in C++... By Default."
Go can't even get it's packaging story straight and once again doesn't have generics which makes 'functional' programming a no Go;)
I actually really like Clojure (really I just love Lisp).
Go also has modules now.
Maybe not fully functional programming, but something that's quite pleasant to work with to be sure.
And it requires acres and acres of generated code, a custom runtime dynamic type system, whacky module names for compatibility instead of a reliable build system like maven, to make the thing work at all. Kubernets is a multi-megaSLOC advertisement for the virtues of Java as an ergonomic experience.
If it had remained in Java it could be incrementally ported to Kotlin. God, what I wouldn't give for that.
Check out Kotlin though. It's seriously great and doesn't share lost of the performance penalties of Groovy
That's a bit of a myth these days. Groovy may even be more performant than Kotlin when used with static compilation.
What does that mean? What does Spring Boot give me that Tomcat doesn't?
Tomcat is a servlet container that implements various Java EE specifications, such as the servlet spec, jsp spec, etc.
Spring encompasses many different libraries. The most widely used is probably Spring MVC, which builds on top of the servlet spec to make building web applications easier. After that Spring Security is probably most widely used, which adds things like auth, CSRF tokens, etc. Spring Data and Spring Cloud are also somewhat popular. There are many more Spring libraries, but I have little to no experience with them.
You can really give or take what you want here. You can use Spring MVC with Spring Data, or Hibernate, or JPA, JDBC, or whatever you want really. One place I worked used Spring MVC with home grown security and ORM layer.
Spring Boot brings "convention over configuration" to Spring. Because Spring is so configurable it can take a lot of boilerplate. Spring Boot removes much of that boilerplate for certain use cases and has, generally speaking, more user friendly defaults.
Spring Boot also runs off a server embedded in the jar. That's why you can "just run" it. You create a "Main" method. You can choose from several embedded servers, including Tomcat. But this isn't exactly special for Spring Boot because you could do this even if you didn't use Spring Boot.
Any practical advice for making this happen? I have a Spring Boot system I wrote and am responsible for, but now I just want the pain to stop.
Like React, you can out together your own "best of breed" java stack. It just takes a lot more work.
Look to replace one component at a time. For DI Guice or Dagger2. For REST Vert.X or Jersey. Logging Logback. Metrics, DropWizard Metrics. OAuth ScribeJava. Hibernate for Spring Data.
Take a look at the "awesome java" repos and choose your poison.
I'll warn you now that while you can end up with something far better you lose the coherency of Spring. Of your organization doesn't have a good "apprentice" setup all the new devs will be utterly and hopelessly lost. And good luck finding a Dev that knows 20+ libraries vs "Spring".
Rolling the libs was worth it for us but probably not a lot of eng orgs
If you're just looking for a drop-in Spring replacement you can't go wrong with DropWizard. It's a solid combo of best-of-breed libraries and has quiet support/adoption by many huge companies
Android?
Which were absolutely everywhere at the turn of century.
Android is the only reason to have to put up with Gradle.
But, yes, is does use a lot of memory.
Eclipse and Netbeans compile on file save, can't get more continuous than that.
2GB for a cache that isn't required by alternatives for the same result just feels bad.
And don't get me started into turning build scripts into full blown applications impossible to decipher what is going on without some kind of debugging process.
Gradle is the worst allergic reaction to XML in history.
I understand not wanting to learn another build tool, but I have no regrets where I've moved to gradle. It's so much faster on a project of any size it's stunning.
90% of maven projects don't do anything terribly complicated. Porting them to gradle leaves them uncomplicated and unexciting. I just wish there was a standard release mechanism. Poor as mavene-release is, at least everybody uses it and understands it.
They don't stay uncomplicated though. Someone puts a quick one-liner hack in the build definition to fix some trivial issue they were having, and it never gets removed, and years later it bites you. I don't trust myself to remember and understand arbitrary code that I put in a build definition, yet alone anyone else.
There's a jetty-maven-plugin? What for? When I use jetty I treat it as a library, embed it in my application, write my own main() and then my application is just a normal application.
> servlet api versioning conflicts
> multiple mvn central listings for the same artifact
These are a genuine problems but they're ones that every mature ecosystem struggles with. Maven has better tooling than most IME - you can use the enforcer plugin to require dependency convergence, and when multiple packages contain the same API you can put exclusions in a common parent. No ecosystem has really solved the problem of package renames nicely, IME.
> ad-hoc scripting using ant plugin
Yeah don't do that. If people will insist on shooting themselves in the foot, there's only so much you can do to stop them.
> shading/fatjar plugin
What went wrong there? IME the shade plugin is very good. There are a couple of inherent JVM-level limitations (having to specify transformers for service locator files etc. because of the way the JVM spec is written) but it's hard to imagine any other build tool could do better.
> fragile local dependency resolution
Not my experience at all - what specifically goes wrong?
> dozens of pointless submodules
Submodules are cheap. IME when coming to work on a new project it's much easier to understand the build/dependency structure if there are lot of submodules rather than a complex build - e.g. rather than trying to have a custom build phase for generating some RPC stubs or whatever, it's fine to just have them in their own submodule and then it's obvious to the reader what the dependency graph looks like. What's the downside?
> A customer of mine even had a solid 3 week outage when they wanted to setup a product for blue/green deployment based on maven.
What? How?
> Makes autotools look like a sane build tool.
Strongly disagree with that one. Autotools has several layers of template/macro expansion that all seem to do much the same thing (so why not just one?) and encourages builds that use arbitrary unversioned command line tools from the host system, meaning you very rarely get reproducible behaviour on a host with a different setup. Maven gives consistent, declarative builds - what's not to like?
Particularly though, the static compilation is just not comprehensive enough. It tries to do type inference but it's limited and invariably you end up having to add type casts in ugly places to convince it that expressions are valid. Occasionally it actually flat out refuses to compile something valid and you have to find a different way to do it. Sometimes it compiles with one version of groovy and then is broken in the next. It works great though to selectively add to hotspots of code and in other places to speed them up and define them better.
Having said that, we are essentially using Groovy as a java replacement and for our team I think the above costs are well worth it. This is partly because we have a heterogenous application that is partly dynamic in its nature and Groovy's dynamic scripting ability is amazing for this. The fact we can code our whole back end in the same language makes it super easy and well integrated.
As for Android, lets see what happens with Fuchsia.
The overwhelming majority of Java developers don't even know who Steve Yegge is.
True. They will drop them because Eclipse has been faltering for ages and has been dropped by IBM, and Netbeans has always been a subpar unloved stepchild used by the kind of devs that don't know better and think SlickEdit or Notepad++ are great editors.
>The overwhelming majority of Java developers don't even know who Steve Yegge is.
That's on them.
Lets talk back in 5 years from now.
I am betting Kotlin would become yet another language that happens to compile to the JVM, after the Android honeymoon goes away.
Still not able to use several of Android Studio features available to Java, like incremental compilation and slim APKs?
Kotlin advocates seem to forget JVM will never be rewritten in Kotlin, the language is just yet another guest, with the usual syndrome to wrap existing libraries, having to take care about FFI for Java access, not having all features taking advatange of the latest bytecodes, e.g. lambdas implementation.
As for Kotlin/Native, there is nothing to worry about versus what Go, Rust, C++, Dart, D, Nim offer in terms of performance, libraries and in some cases tooling.
Having to buy CLion for a graphical debugger isn't a selling point versus the established alternatives.
Fuchsia is being written in Go, Rust, C++ and Dart, with the team now hiring for node.js support.
https://www.androidpolice.com/2019/03/19/google-working-to-b...
Seeing that both Eclipse and Netbeans are now more or less dead (and speaking as a long time Eclipse user, from the very first version to around 4), yes, first class vendor-direct InteliJ support is more than enough. And more than most languages (including Groovy) ever had.
>As for Kotlin/Native, there is nothing to worry about versus what Go, Rust, C++, Dart, D, Nim offer in terms of performance, libraries and in some cases tooling.
IMHO, Rust will always be kind of niche as hard to tackle, Dart we'll see, D never went anywhere, and Nim will remain niche, it's a little too idiosyncratic to catch on.
Kotlin is already more popular than all of the above except perhaps Go.
>Fuchsia is being written in Go, Rust, C++ and Dart, with the team now hiring for node.js support.
Fuchsia is still vaporware or at least irrelevant. It's not even in the market yet. And the fact that it's written in 4 (and looking for 5th) languages doesn't really bring much confidence.
We move in different worlds, no InteliJ installations around here.
I remember when Groovy was popular, with every JUG in Germany having weekly talks and Sun talking how the next JEE revision would support Groovy for writing beans.
Popularity doesn't write software.
That won't get kotlin more traction. No proper/official tools for LSP support means no vscode, vim, emacs etc. users. As a happy eclipse user, I wouldn't call it dead either.
When I was developing a VR game, my team noticed that some ultra-sensitive people started to get sick when we would drop around five frames (the vive displays 90, so this is only a ~5% drop). There was more to it (dropping a few frames every few minutes was usually fine, but consistently dropping frames every second or two is an issue).
If GC only causes occasional (maybe every 2 minutes) loss of a frame or two it should be no problem. If you watch benchmark FPS traces that count every frame delay you'll see that occasional stutters happen in basically every game.
Loss of a single frame just isn't noticeable
And some games much later didn't. I recall needing to fire off a shot on each new gun I picked up in Far Cry to be sure I wouldn't get a stutter later at a more critical moment.
Streaming/Loading assets in the main render thread is a very 2005 thing to do.
Use it all the time :)
God, all the fussing with threads and fork-joins and mapreduces and god knows what everyone else wanted me to do: gone. Gone!
One thing you should know is that parallel streams use default thread pool unless you specify otherwise. Had that choke up some REST handler threads a few times. If you think it might be an issue make sure to specify a different pool
I think my question is, do most Java developers really know what goes outside of their window? Every language has a good story for web apps these days. The web is ubiquitous. You can write in Phoenix, Cowboy, Rails, Sinatra, Express, "net/http", Django, Laravel, Flask, Rocket... Java is literally middle of the pack at best. So that's not a compelling reason to use Java. So then we have to look at the rest of Java. Is there anything else in there that would make it better for web dev than a simple Go/Ruby/Python/Javascript/Rust/Elixir app? No? Ok, then let's not use Java. Java excels at being mediocre at everything, but the best at nothing.
Ask Twitter how their Rails apps is holding on.
A warm JVM is faster than a greased millenium falcon.
There is a lot of software running in this world. Some of it is very long lived.
Other open implementations exist from Amazon, IBM, Microsoft, Zuul etc. And they are all using the JDK name which isn't owned by Oracle.
If Oracle were to die or become aggressive the Java ecosystem would just move on and not skip a beat.
For people actually working with JVM and the languages on top of it, nobody really is worried about Oracle. The way the licensing is set up, they just don't have enough power to coerce people to use their version. It would kind of be like the SCO case if they came after it. I think they went after Google for Android simply to protect their IP, and that one they even "lost" (which detracts also from their possible future lawsuit on enforcing Java licensing)
Most of my apps just code against the servlet spec with a JDBC connection to a MYSQL database, sometimes with JSP. Perhaps because most of my business logic lives on the client I've usually found that plain servlets + plain JDBC calls were sufficient
Although I've found it pretty straightforward to configure servlets in Tomcat I can see that Spring MVC makes it a little easier. Maybe the introduction of a framework 'Model' is also an advantage - I'll investigate further.
Regarding Spring security - would I use this package if I was implementing a "Login with Email/Password or Facebook or Google" feature to a website?
Not forgetting that dependency injection -- the original core feature -- is just the bee's knees.
I work for Pivotal, but not on Spring. But I've definitely grown to appreciate it more and more over the years. I deeply miss it when mucking about in Golang.
They probably did. They're late for all memos. The Fortune 500 is not were you'll go to gauge adoption. Heck, half of them still have IE6 only apps.
There are hundreds of thousands of companies, and just 500, well, Fortune 500.
Apparently you use the most established and boring development-wise of companies (Fortune 500) to prove Kotlin is not used widely, but you're OK with vaporware like Fucscia that's not even beta yet as an argument that Dart and co are.
>I am betting Kotlin would become yet another language that happens to compile to the JVM
And I bet you're wrong. Let's see in 5 years. We were on HN 10 years ago, we'll probably be here then. I'll set a reminder.
Not sure what the special deal is with Fuchsia here.
Perhaps you think you'll be able to write Fucshia device drivers with any language you like? That wont be the case at all.
Also Linux has this going in its favor over Fucshia: it actually exists.
What's so remarkable about that fact?
It's not that Spring is badly coded or something, I just don't need these surprises and the magical thinking surrounding newbie Spring Boot projects.
Nothing.
All the carefully crafted validation annotations just don't do anything, no validation is performed, and there is no indication whatsoever of this.
I had a problem with security that I could only solve by adding an "Order" annotation to my class. Reading the code and stepping through it in the debugger did me absolutely no good.
Isn't that true for all other languages you mentioned? python, erlang, php, golang bundles a runtime, etc..
Go and Rust are interesting to follow. A highish and low level language both using lightweight runtimes
I smell a zealot or a troll.
Smalltalk is exactly like that - other objects' state is only mutable through explicit message passing. It's also widely considered the penultimate pure OO language.
> Pretty much all of the OO languages are walking back OO features
About the only feature I can think of for which this is somewhat true is inheritance, and that's because we realized that aggregation is often a better model, and can be easily supported by the language to be no more verbose. But it doesn't fundamentally change OO - it was never about inheritance first and foremost; I mean, prototype-based OO doesn't even have that conceptually.
> and trying to add type classes (contracts)
In most OO languages, these typically naturally evolve out of interfaces.
> functional pieces, mapping and filtering a la linear data transformations.
This is not contradictory to OO in any way. Again, Smalltalk has had "select" (filter) and "collect" (map) from the get go.
Lombok makes immutable data classes trivial. Improved interface support for default methods make it possible to largely ignore OO if you don't want it.
FP is mostly a community effort at this point, but solid. Java Streams are decent for basic stuff like map/filter but RXJava is extremely powerful if you want the complexity it comes with. Vavr is nice for adding more FP types too
IMO Java is the most well rounded language, but I'm not trying to convince you of that.
Also there's nothing with java that stops threads from being restarted. In a modern web framework it's virtually impossible to crash the JVM. You just crash a thread, at most (usually the framework catches the exception and it doesn't even do that). Java is also hot reloadable if you use the right framework.
Your tooling argument doesn't make much sense IMO. You can attach to a Go binary but that's about it. Attaching to a VM or interpreter will tell you almost nothing. I would wager you haven't used a Java profile if you're making these arguments. It's vastly superior to anything but maybe C#
You’re not understanding what I’m talking about when I say restarting. I’m talking about the JVM process. I also just said hot reloading is counter to modern practices.
You’re not understanding what I told you.
You can also compile AOT for some performance loss at runtime but zero startup time. Android has been doing this forever but you can also do it on a PC using Graal.
And yes Java will destroy Erlang at concurrent connections if you use an async framework like Vert.X or fibers using Quasar/Comsat. It has lower per thread overhead than Erlang and runs code faster in general.
Both Java and Erlang will max out Linux TCP connections before running out of steam so this is kinda academic though
I don't drool over the raw horsepower of each of my individual boxes.[1] All I care about is that I can cost effectively create a cluster of them to serve the application's needs.
Because of this, even if Java could not handle as many concurrent connections, you might still chose it over this fabled 10M socket erlang server you keep talking about.
You might chose Java because:
* It is well understood and has a lot of mature libraries surrounding it.
* You can easily hire people to work on it.
* It is a stable language.
And so on...
I would summarize your original post like this: "I don't like Java, I prefer other things," which is fine as far as it goes, but then you basically say: "Therefore, everyone should also prefer the same things I do," which does not follow.
[1] I never particularly cared how many fps I can get on my machine, and I'm not that chuffed about my machine's geekbench score. IMHO this obsession with hardware metrics beyond diminishing returns is mostly a gamer thing.
[1]: I prefer saying Java platform rather than JVM, because a program written in Kotlin shares over 90% of its infrastructure code with a program written in Java (not including the OS), and the JVM constitutes only about 20% of that.
So it isn't like just exchanging one for the other like that.
.NET Core 3.0 will fix some of the compatibility issues but not all of them, for example EF 6 will only be partially supported (VS DB tooling is not being updated for Core).
It's the ridiculously large JVM ecosystem that makes Java awesome, not the language.
I have love for Java, but I gotta say it mostly is because the ecosystem is pretty fantastic. So much open source stuff for so long means it's all just there and it all just works. There are some gaps though.
.NET ecosystem isn't bad. It's pretty good. There are some phenomenal libraries. But sometimes the gaps are painful. The lack of an open source (read FREE) integration framework is a big one for me. There is BizTalk but that's commercial and probably expensive. Same with scheduling libraries. HangFire looks great but it's paid. A lot of the really high quality stuff you have to shell out for which when you're just hacking in your own time is not feasible. That being said there are open source libraries and some of them aren't bad. Lots of great stuff in general.
But the lack of ecosystem is killing them. And has been forever. The new MS CEO is great in my mind but it will take many years to turn the ship around. Devs don't forget.
Best example I can think of (was a C# guy for years). Resharper has been around forever. But it costs a lot. This is par the course for C#. I can get the same thing in Java by pulling in a few linters with Maven, and it's all free. Because MS scared away everyone that was afraid of licensing fees (ie most academics, the sharpest devs out there), there's nothing comparable.
Same with C# port of Quartz and so many others. They killed off the real rockstars among us that create the majority of libraries that everyone else uses.
Can it be fixed? I hope so. The CLR is great and Oracle sucks. But for now there's a good reason Java is dominant
They also have a perpetual license. If you cancel after the first year, you can keep using the version that was current 12 months ago.
But the one thing missing in Java is anything like LINQ. I don’t mean the syntax I am referring to the idea of LINQ -> expression trees -> third party providers that translate LINQ to another language (sql, Mongo Query, etc.).
I do miss LINQ though. The Java options are all clunkier because the type system isn't nearly as flexible
Also, .net is more of a “pit of success” language — Java with all its legacy baggage requires a lot more knowledge to avoid mistakes.
Can you give some examples, that wouldn't be equally applicable to Java?
I know, I've used it. What I said is that it did not have the first class IDE attention of a major vendor, those were mostly third party sub-par plugins compared to the Java focus of those IDEs. For Kotlin, however, it was first class IDE support as a primary concern from the start.
>We move in different worlds, no InteliJ installations around here.
Then we indeed move in different worlds.
>Popularity doesn't write software.
No, its just the only thing that matters when it comes to get paid for it.
Had it not been for Google's adoption of Gradle for Android and it would have been left for Grails maintenance projects.
And even then, the pressure for perfomance has been so much that it is being superceded by a Kotlin based DSL.
How to improve Gradle has been a common talk at every Android conference since Android Studio has been introduced.
Google Trends says Groovy is just as popular as it was 10 years ago. The number of downloads has increased significantly but it is not because of Gradle, as Gradle bundles Groovy. It is also currently placed #16. on TIOBE Index
And last, Groovy with compile static is in most cases, just as fast and memory efficient as Java.
Some people always talk down Groovy, yet the numbers speak for them self. Before Kotlin, Groovy was attacked by Scala developers.
The major thing Groovy has over both Scala and Kotlin is strong similarity to Java syntax which makes the learning curve non-existing. And that is a bigger deal than a random cryptic/confusing programming expression. Code readability is very important.
Telerik and the likes I'm not so fussed about personally. I suppose DevExpress is another one on that list. I think front end component libraries like Prime-ng/PrimeReact are probably the way to go for the future of UI development for Line of Business applications.
Overall I reckon in a couple of years there won't be much of those blockers left at all.
As Hejlsberg explained, the problem with virtual-by-default is that every time one of your public methods calls another public method on the same object, it makes it that much more complicated to reason about your invariants. If the called method is non-virtual, then you're in full control, and you know exactly what happens. But if it can be overridden, then you need to define a contract for overriders to follow, and you can't assume that it does anything other than what's expressed in that contract (in particular, you can no longer call that method without ensuring that all class invariants hold, even if it's expensive). Furthermore, the overriders often also need to know which other methods on the class do or do not call this method.
In practice, this is so much hassle that not even the Java standard library does that. For example, given ArrayList, if you override add(), does that affect addAll()? The docs don't say. So in practice, the only things that are safe to override is what the docs say are safe to override... which is to say, exactly like "virtual", except it's not enforced by compiler. Overriding random methods often works, but is a hack not dissimilar to using Reflection to access non-public members - even if it works, you're relying on implementation details of the class.
Many of those numbers are fake. Groovy was #70 on the Tiobe index only 12 months ago, see [1], but is #16 now. How do you explain that? Groovy was last in Tiobe's top 20 about 2 years ago when the search numbers for "Groovy" from Baidu were hugely incorrect. Groovy later quickly dropped back out of the top 50.
https://trends.google.com/trends/explore?q=%2Fm%2F07sbkfb,%2...
Java worldwide average 86%
Groovy worldwide average 2%
Pretty popular indeed.
Person.Get(p => (p.Age > 65 && p.Sex == "M") || (p.Age > 63 && p.Sex == "F"))
and have a method public List<Person> Get(Expression<Func<Person,bool>> expression)
and have that expression interpreted correctly at run time by separate providers?You get full compile time checking and IDE supported autocomplete.
The Java code "looks" like they do the same because they generate code to simulate method references instead. It's pretty clever and Javas code generation support for Annotation Processors is excellent and makes it possible to do this in a cross-ide cross-build-system way
LINQ and JOOQ/QueryDSL all work on plain data objects with fields. But with Java you do it on a pseudo object generated from your existing classes
All of these years I've been beating up on Java for lack of something akin to LINQ. I guess I'll have to find something else to complain about.....