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

[flagged]



Having worked extensively in Java, Node, and Python, I’ll take the JVM ecosystem absolutely any day of the week.

Me and my catheter will be over here delivering actual software while you figure out how React 32 broke your transcompiler.


No idea why you are comparing Java, which is BE, to React, which is FE.

I think I will check Java once they finally make coroutines… I mean “virtual threads” a stable feature. That actually looks exciting… being able to parallelize almost like in Go 5 years ago.


>finally make coroutines… I mean “virtual threads” a stable feature

Don't you mean fibers? Anyway, I'm pretty sure it's targeted to JDK21.


Fibers are now called virtual threads


Except I’m over here serving 10x the traffic with 10x less cloud spend on CPU and Memory for hosts.


In what language would that marvel be? I give you the less memory....


Go has goroutines which have better cpu and memory than threads which are commonly used in java.

Java is now catching up with go and adding virtual threads which in september 2023 will have the same ease of use as go had in … 2007?

But as I wrote above, it migh really get me to check java again.


Well is it correct that until 1.14 (so 2020) Go used cooperative scheduling? Because Java Threads, (before the new virtual threads) are preempted by the OS...Go was launched in 2009? Who is doing the catching up?


Maybe you should upgrade from Java 1.4...


> delivering actual software while you figure out how React 32 broke your transcompiler.

Say that to enterprise software systems still running on Java 7 or 8 without any clear path to upgrade because their whole systems will break.


It’s almost like there is even a CS law for this exact scenario.. but Java 8 will be around and will still work 10 years from now, plus it is not an insurmountable task to bump it up to the latest version at all. Tell me literally any platform that has a better backwards compatibility story, because honest to God there is simply absolutely none.


Java 8 will be out of support in 7 years. It might seem like a lot but for enterprise systems it's nothing.


Which gives you a lifetime support of 16 years for a single version, with an absolutely sane and doable upgrade path.


C++. And it’s hated for the same reasons.


Do you feel good about yourself, talking down on people that made a perfectly valid choice by developing software in Java?

Let's look at the alternatives you mentioned: Rust and Golang. Java compared to Golang is a much more expressive language. Java compared to Rust is a much easier language because you have a garbage collector for the majority of the cases you don't need the manual memory controls that Rust offers you. In other words, Java is a perfectly valid alternative to both Golang and Rust with its own tradeoffs.

You try to paint a picture of Java not being cool but at the same time I see "modern" companies that are held in high esteem for their engineering prowess using Java to do incredible thing (e.g. Netflix and Google)


Google invented Go.

Netflix uses Java and Rust and Go.

Twitter used to use Scala.

GitHub uses Ruby on Rails.

EpicGames uses C++.

Instagram uses Python.

Everybody uses something.

Now, if you have building on top of your organizations previous 10 years of engineering, you’re probably going to be writing Java and it’s probably going to be complicated. I’ve been there. I wrote Java for 15 years. I won’t anymore. I’m in love with the simplicity and speed of Golang. I’m in love with the robustness and correctness of Rust. I’m in love with docker pull scratch:latest and putting your binary inside to run on an empty metal container. No need to waste 250MB of ram on a JVM. Use nano size instances and it’s just as fast as c5’s (async based workloads).


> Google invented Go.

A handful of people at google invented golang is the more correct thing to say.

Yet, google continues to use Java at a much much bigger scale than golang.

golang is simplistic, not simple. Once you work on large golang code bases you'll see the challenges and messes it causes.


I work on really large go codebases


You're trying to make the point that the only companies using Java are doing so because of legacy. That is demonstrably untrue. Netflix and Google have had ample time and capacity to replace Java, yet they didn't.

As any good engineer, people working at those companies recognize that Java, Golang, Rust etc. are all tools and these tools have their place in different scenarios.

I used to be like you, but my personal "anti-language" was PHP. I would talk down on organizations using PHP and I would take them less seriously as engineers. But I have come to see that they too are using a language (PHP in this case) as a tool to build a business. And it serves those orgs well apparently.

Don't get me wrong, Java would not be my first choice in many cases. At the company I'm working for, we only use Golang and Python in the backend and Typescript in the frontend. That doesn't mean that I cannot recognize the value the Java can bring and the niche it occupies.

I'm actually pretty amazed by how far Java has come as a language. 10 years ago, I thought Java was going to be replaced by the likes of Kotlin or even Scala. But Java has pretty much caught up in terms of features and ergonomics compared to the Kotlin and occupies a comfortable spot now as being an expressive and productive language without bringing the learning curve and footguns of Scala.


Manual memory controls? What are those? Rust does not have "manual memory controls". You write the code so that the borrow checker does not complain. End of story.


Those are pedantic semantics. I assume you know what I mean. But I'll explain it to you: with Rust you are in control of how memory is managed. Indeed through the borrow checker.


So which is the real programming language one should use in the God's year, 2023? (Will it change in 4 months also?)

> virtual threads but you still have threadpools and os threads

As opposed to what, quantum entanglement threads?

> No one really enjoys debugging your call stacks

Frankly, debugging has probably the very best tooling around the JVM -- so, what exactly is your chosen favorite that would be supposedly better? Or is objective reality not hyped anymore?


Yeah, I dislike Java more than most but picking on its debugging story is laughable: it’s tooling around that is excellent


I just picked up Java (via Kotlin) for the first time in four years, during which I've been doing Rails dev. I needed an AWS Lambda for zipping files into and out of S3. I banged my head against broken/unsuitable Node packages for doing so before finally giving up, since it is the lingua franca of Lambda.

I was able to rewrite and deploy the function in Kotlin in two days' time. It was easy to set up and run, and worked literally first compile and run - a benefit of static types.

Now, would I recommend it to anyone who is unfamiliar with the JVM ecosystem? That's a harder sell. But the stability of the ecosystem and a modern set of saner tools and libraries have made it much better to work in; I'd even call it pleasant.


AWS Lambda is the once place where you should never use Java. You have specific thresholds for how fast your function responds, jvm prevents that and requires more memory.

AWS Lambda’s documentation shows how to accept a Request and send a response. You don’t need a package for that. For making zips from s3, again, AWS’s sdk. It’s one of the most commonly asked questions on SO. Here’s one implementation for you that could have saved you days:

https://stackoverflow.com/questions/38633577/create-a-zip-fi...


Trust me, I looked up dozens of references. All would mysteriously halt after several files - known issues with how the Archiver library works, and none with any kind of fix, basically a data race within the library itself. Node's streams and promises are far too complex for far too little added benefit, and leads to broken concurrency in a multitude of libraries, and I'd had enough.

As for startup time - the latency isn't that important and would be an order of magnitude less than the ZIP construction, so the JVM warmup delay is actually just fine. The cost will be slightly higher, but it's not an operation I expect to run with high regularity - it's only on-demand for a reasonably small userbase.

As for complexity - which I am able to weigh due to the above constraints - Java's streams are not only simpler in design, but vastly more stable, and far more straightforward to glue together, and with highly stable implementations of ZIP stream wrappers and output-input pipes. A couple of additional stream wrappers for chunking into multipart upload segments and forwarding streams (introduced in JVM 9 when I'm on 8), and I was ready to go.

All that to say: don't create universal rules, though I agree that all of what you mention are good rules of thumb for certain. My given constraints work just fine with Java, here.


A minimal Java app can easily start up in 0.1 seconds, which might just as well be good enough, but if not, there is also GraalVM that can output a native binary.


I’ll just leave this with you. 0.1 difference may not seem like a lot until you start hitting 100M invocations.

https://mikhail.io/serverless/coldstarts/aws/languages/


Wouldn't you have a lot of warm starts with that many invocations?


At that point, why lambda?


Exactly what is enterprise? I think Java has a role to play in most professional settings, even if the company is quite small. It is not a sports car but I see it more as a truck or a cargo ship. Vehicles that underpin the world economy, but that only few think of as fun or exciting. Not pretty or nice to look at, but reliable work horses.


It is for sure the wagoneer when it comes to getting things done in the enterprise, if it was 2005.

It’s not a sports car, it’s not a dune buggy, it’s not even pretty in its wood paneling and drab paint scheme. But it got your family to Wisconsin for the holidays.

In 2023, we have better options.


Yeah, sure the thing that runs the whole of Apple, Alibaba infrastructure, many part of Google, most of that "cloud" infra is a wagoneer..


Such as...?


> No one really enjoys debugging your call stacks

Of all the things to criticize about Java, this IMO is not one! A Java call stack is a joy compared to just about anything but Python.


It's not so bad. I might be an old masochist with Stockholm syndrome, but every language has its own special flavor of barely tolerable bullshit.


There is some truth to this. Every language I used had severe drawbacks. At this point, it's choosing the lesser of the evils.


so, which lang would you use personally?

> you still have threadpools and os threads.

why this is a bad thing exactly?


Golang or Rust. If it’s a web service or microservice: Golang hands down. If it’s a desktop software or game engine, rust. If you just want to typescript your way to success, deno and vite. If you’re too introverted for Rust, Zig.

Java, whether it be spring, micronauts, jee, whatever, is wasting CPU and Memory in the cloud costing you and/or your enterprise money.


> Golang

golang is probably a good contender for business logic code where Java is widely used, but I feel ecosystem (libs, integrations) is not comparable to Java, so you take some risks while choosing golang.


And it is much more verbose, it is not even comparable in observability and on real world big applications (especially enterprise) you can't get away with value types and slowing down the threads to let the GC keep up with them -- Java definitely shines in these kind of conditions (GC-wise the only competition Java has is different Java GCs, really).


> you can't get away with value types and slowing down the threads to let the GC keep up with them

I am not Go expert, but to me this is Go's big advantage: you can chose you want to have object GC controlled or be on stack and copied everywhere. GC controlled objects add lots of overhead, because malloc is expensive, and require lots of memory per object to track state and synchronize between thread, and that's why JVM tries to adapt something similar: https://openjdk.org/jeps/8277163


Sure, value types are a good thing, but they are no panacea in and of itself.

Also, any non-toy GC won't be using malloc, e.g. in Java's case allocating objects is barely more expensive than allocating them on the stack: they use a so-called thread-local allocation buffer, which can be used to allocate new objects in, without expensive synchronization, and the GC can quickly scan it, moving still alive objects out of it, and clearing the buffer.


> they use a so-called thread-local allocation buffer, which can be used to allocate new objects in, without expensive synchronization, and the GC can quickly scan it, moving still alive objects out of it

yeah, all these logics still have significant overhead, especially memory wise, it is hard to reason when JVM decides to kick that or another optimization or not kick anything at all.

With value objects you have full control and bare-metal-native performance without compromises.


> you have full control and bare-metal-native performance without compromises.

Not even you believe that, right? Especially with regards to Go.. Go is closer to JS than to Rust/C++.


as soon as you copy your struct by value around, it is easy task for escape analysis to decide to put struct on stack.

also, golang has arena API now, and it also makes heap allocations super cheap if you manage to integrate it into app life cycle.


Golang doesn't have copy elison unlike C++ so in principle you need to leverage the heap escape anyways.

Golang's arenas were an experiment that has already been ditched by the maintainer as un-feasible.


> Golang doesn't have copy elison unlike C++ so in principle you need to leverage the heap escape anyways.

I mean you can pass structs by ref or value around, which makes direct impact will they be on stack or heap.

> Golang's arenas were an experiment that has already been ditched by the maintainer as un-feasible.

Thank you, good to know, looks like big pros in favor of rust as lang for my next project.


I have not used Go generics, but it's viability as a business logic language would depend on that.


Wait, what?

Generic programming is a perfectly valid style, but are you saying it's essential to implement business logic?

Because, like, the last 3 languages that got adopted as the default business logic language didn't have them (Java pre 1.5, C, and Cobol).


It is not essential, but without it, it is much more cumbersome. I programmed it with Java so I know it can be done but I would not choose a language without it if I could.


It is absolutely necessary nowadays, yes. Our applications are often more complex than what people did in Java 1.5, Cobol, or C, and definitely need to be developed at a faster pace.


and during last 20 years consensus has converged to the view point that generics are essential.


Huh. Guess I'm heterodox, then.

I mean, don't get me wrong. It's quite useful once in a while, especially when working with containers, but I don't think of it as essential.

But I'm fine with it as long as people don't overdo it.


Rolling your own containers really really sucks. Sucks enough to the point that it is essential, in my books.


Maybe I should be more clear.

This thread was in the context of go generics, which generally means go 1.18, when user defined generics were added to the language. Go always had support for a minimal number of containers, I've never rolled my own when working in the language.

Go had special compiler support for slices, maps, and channels before then, and they got used as the default containers for everything.

Using those was annoying when you needed to do the same thing to, say, a slice of strings and a slice of ints, but if you aren't using a generic heavy style, it actually comes up surprisingly rarely. And, if I'm being honest, I'd consider most of the uses of generics I've seen the average enterprise dev use to be mistakes.


they have generics now, but there are other conceptual shifts:

- no inheritance

- error codes with explicit handling everywhere


no inheritance but there are interfaces to be able to provide alternate implementations. Similar to traits in Rust. If it quacks like a duck, has feathers like a duck, swims like a duck…

Go just assumes if you satisfy the interface, you’re good.


maybe, it is just some effort for someone who coded in classic OO for last 20 years to wrap head around this new concept fast and judge if it will satisfy all/most use cases.


Yes those are also drawbacks


golang is a simplistic language which lacks the modeling capability of Java, so it won't do well in large business code.


TIL that projects like terraform are - apparently - not "large business code".


You can write basically anything in any Turing complete language, doesn't mean it's a good idea.


This ... is how you make engineering choices?


At work, I have a different context. What is the common denominator of what people know. Personally, the “write once, run everywhere” notion of Java has been replicated with much more productive languages.


Sounds like you're talking about a pop band, not a tool.


Call me back once golang is going to have anything close to visualvm and remote profiling capabilities.

Is golang still using mark and sweep gc?


I agree, Java is wordy, ritualistic, and prone to overcomplication. Build/run/write loops are slow and painful, and frameworks and toolkits try to do so much that they inevitably get in the way.


Not by that much... the problem is Java's build systems. Theyre what complicate and slow down java development 90% of the time.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: