What else do you want from the ecosystem?
I remember programming Java in Eclipse. And it was powerful for the time, but everytime I read bloated, I automatically think Eclipse since then..
I’m sorry, I’m calling BS here. You can still leak memory in Java.
Java obviously isn’t thread safe like Rust is, but it’s typically safer than C++ on that front too.
It's up to the programmer to verify the safety of code using unsafe. But it they do so correctly then you can rely on the borrow checker to verify that everything else is safe.
This means that when you run into a thread safety bug in Rust code you should only have to look at the unsafe blocks to find the culprit.
In java, race conditions can enter illegal application state, but their scope is much more limited. NPEs are 100% safely handled, etc. you can only get off the safe road with using Unsafe unsafe, and manipulating the JVM’s inner state which is not even allowed by default. Depending on application, this difference may matter a lot!
while (true) { list.add(1); }
Here you are, which language won't leak memory here?
Also, which language will let you connect to a prod instance without a performance hit to get some stats on the heap and its allocated objects? Hell, you can even list every instance of a type as I've recently learned.
> while (true) { list.add(1); }
idk, I don't think endlessly growing memory usage is really what a leak is, a leak is really when you have no way of accessing the allocated memory to free it (ex. dropping the last remaining pointer to a `alloc`'d block in C) or the opposite in garbage collected languages: accidentally holding onto a strong reference to objects that should be freed.
So basically what I gave an easy example of. Sure, it won’t look like this in practice, you probably accidentally keep adding to a list, or a cache, but basically this is what happens. The former kind of leak can’t happen with tracing GCs.
Every time I see something like this I roll my eyes... C++ doesn't have any "memory problems".
There are sometimes human problems, such as thinking one is capable of coding without understanding the (basic programming) concept of a pointer. But that's because the human's dumb, not a language problem. (This argument also sometimes comes from those who do understand basic programming, but are only familiar with C++98.)
> Thousands of high quality libraries a JVM that is a marvel of engineering after 20 years
I reluctantly have to agree. :)
If everything is the programmer's fault for being dumb, then Brainfuck is an excellent system language.
You can choose which report you would prefer: Microsoft's, Google's 65%, ... I'm sure they just hired bad developers that don't understand pointers.
Sure, human problem, but if no human can use the tool correctly, then surely there is some problem with it. And no, that doesn't mean that memory unsafe languages don't have a place, but we really should have a very good reason for going down that road.
Well, every time I see someone claim this, I roll my eyes.
It can do most anything. It can do it most anywhere. And you can code in it using several different paradigms.
It’s easy to install, it’s easy to be instal several versions, the footprint, by today’s standards, is not enormous.
It’s easy to deploy, especially server side. While you can certainly do all of that modern stuff with containers and what not, it’s not really necessary for Java. Drag and drop a JDK install, anywhere. Plonk your Java server code, anywhere, and point it at your JDK, and. . .that’s it! Fire it up. The JDK is remarkably light on dependencies.
And since most Java apps are “pure Java”, the apps rarely have a dependency outside of the JDK. And since Java apps routinely bundle their Java dependencies, the apps don’t stomp on each other either. Even SQLite bundles it’s binaries in the Java Jar file. So wherever that jar goes (again, and typically bundled with your app), SQLite goes. No floating dependencies.
Desktop bundling requires a bit of search engine research, but it’s doable. And the runtimes can dwarf something like Electron installs.
As a language is Java ELEGANT? Not particularly. It has its own elegance in some areas but that can break down or get overrun in others.
But, boy howdy, it sure is practical. The ecosystem is so huge. It compiles really fast. I marvel at the stories folks tell about their dev cycles in other languages. How do they get anything done, besides sword fighting?
I love Java, but I’m very comfortable in it. But the Maven based dependency system works, it’s huge, it makes use and reuse simple. The IDEs are powerful and mature.
And, finally, Java’s not dead. Hardly. Oracle has been a surprisingly good steward (with warts, as always). The language has been on a rocket of development and shows no sign of slowing down. Server side is still very hot with all the frameworks and all the different approaches. Things like GraalVM taking the JVM in a whole new direction.
And, yea, that. I’ve only been talking Java the language, not the JVM itself per se. That’s a whole other thread.
Dependency injection frameworks are your bread-and-butter in server-side Java, and some can take a while to grok, but Java can be very productive after the chosen framework "clicks" for you. Typically, this means you'll be writing constructors or factory classes that construct your dependencies per request. The way you wire your factories into the system differs by framework, but it often involves using Java's annotation syntax.
Not having to worry about memory management is a huge win for productivity over C++. Likewise, constructors in Java are much more sane than in C++.
Classical object-oriented programming is intuitive, and Java tends towards the "one obvious way to do something" paradigm. I find it pretty easy to hop into legacy code bases, if I already know the framework being used. The collections API in the standard library is one of the best classical OO APIs out there.
The JVM provides great visibility into the performance of your system. A lot of instrumentation comes "for free".
I'm not sure where you get the "dirty" and "bloated" feeling from. By any definition I can think of for those words, Python would be in the same bucket.
There's as much useless junk in Python's standard library as there is in Java's.
you can chose to not use DI frameworks at all..
Without DI, there's too much flexibility in how objects get constructed. If you want to add new functionality to a legacy code base, it can be difficult to track down the different integration points and slow to plumb through your dependencies. These projects can turn into spaghetti very quickly.
DI solves this with a simple recipe: define your functionality, define your dependencies, wire it up to the injector.
The pattern is useful in all OO languages, Python and C++ included.
I started using just static factories in my code, and abandoned all those DI and it works well enough.
> I started using just static factories in my code, and abandoned all those DI and it works well enough.
i have done this as well (though not in java), it makes knowing what gets initialized how and where much easier and faster to debugI love Python, and I've been experimenting with Rust and enjoying it so far, but this situation could have been better handled, I think.
I agree 100% about scientific Python though. It's a whole new level of horrible when it comes to dependency management.
The language gets updated regularly and is managed very competently. Although it may seem to trail on some aspects vs other langs, it benefits from second mover advantage - new features are done right, for the right reasons.
Any Java code ever written is essentially eternal, both in text and compiled bytecode form. Compiler and VM compatibility guarantees are unmatched. You can stumble upon 20 year old code and just use it.
The platform is mature and robust. The JVM itself is a marvel of engineering.
The ecosystem is extremely rich. There isn't a problem that wasn't addressed by a library or a stack overflow question.
The tooling is unequalled. IDEs can reliably perform large code transformations because there is no preprocessor or macros and the type system is relatively sane.
If you know Java you'll never be out of a job.
Like I academically understand disliking Java but this just makes no sense.
But if you are talking about the source code itself, then things are quite different.
I'll answer your question with a question: Have you seen https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris... ? :)
I'm guess that to those of us who remember when Java came out, "FizzBuzz: EE" is what we think of when we think of Java. :P
In Java I have to type a bazillion characters to get anything done! And make all these useless directories and files and InterfaceClassFactoryProtocolStreamingSerializer BS. And worry about how that executes.
C++? No bloat*, just speed
*Yes, there's some _optional_ bloat. But compared to Java? no contest.
You have to do literally none of these things to write working Java.
I agree C++ is bloated in a 'just make it a setting' / 'add this feature' / 'kitchen sink' sort of way.
I agree Java is bloated in a boilerplate, empty directories, maybe except for another directory, 'oh god the boilerplate' sort of way.
Interesting. Can you expand on this, explain more? I honestly don't know what you mean or are referring to -- and I'm a heavy modern c++ advocate -- but suspect if I did it might expand my mindset/viewpoint a bit. :)
I think a lot of people wish it had stayed at say C++7, a mature C superset, but that's enough now. I probably should have said 'I understand' rather than 'I agree' - I don't feel strongly, I don't use either of them.
Yeah, C++ is a living language, I can respectfully see that bothering some people. I viewed c++98->c++11 as essentially a new language with c++14 and c++17 being "bug fixes" for the "new language" that is c++11. But certainly, it can require more learning about every decade now.
I can see that being used as a reasonable argument for bloat.
This is just incorrect use/understanding of Java’s execution model. It does have a runtime, but it is definitely not a VirtualBox VM.
The bytecode interpreter for Java (and other similar languages) is literally called a Virtual Machine, due to the way it functions:
https://en.m.wikipedia.org/wiki/Java_virtual_machine
It would seem your understanding of the Java execution model is flawed.
Because there is plenty of bloated and dirty stuff in C++ and Python too.
* Threads that can use more than one core.
* The best approach to package management I've ever seen, no-one worries about typosquatting or "someone already registered all the cool crate names" because every package has at least two coördinates - a group id based on a DNS entry you must be able to prove you have access to, then the package name. So I can publish my malicious package gauva, but as I can't register it with the group id "com.google.guava" or even "com.google.gauva", no-one is going to mistakenly use my package.
* No fucking dance of the C libs. Or Rust these days. I want to use a Python package that wraps a C lib, but there's no binary wheel built for my version of Python and/or platform arch, so build from source it is. Which I'll figure out when pip install -r breaks, and then I get to a) apt-get/brew/etc. install the lib and/or headers b) install any compiler toolchain needed buy not yet present c) export compiler flags and header locations d) all of the above, and then run my pip install again. Until the next library breaks.
* Intersection types for generic bounds. I don't need it that often but when I do, I really miss being to say that for `def foo(ex: T) -> Z`, T must implement interfaces A and B.
* Logging. Occasional horrible security holes aside, Java's logging story is one of the best I've ever worked with, compared to it, Go's sucks, Python sucks more, like how you can't set your preferred timestamp format AND include millis without writing a custom formatter (seriously, go look at the source code of logging.Formatter.formatTime...)
* JMX and MBeans. Having detailed VM performance metrics and the ability to change exposed values or execute an exposed method at runtime built into the VM is amazing. Want to have a quick look at what's happening with the GC? JConsole in. Want to set one logger in particular to DEBUG to see what's going on in prod without having to restart anything? JConsole or jmxterm and away you go. Want to experiment with your batching parameters under prod load to find the sweet spot for throughput? Expose them via an MBean.
* No need for pyenv, virtualenv, etc. Although being fair, if you're working with different incompatible JDK versions, you'll usually end up using SDKMan like Python uses pyenv, and Maven needs a little bit of additional configuration to locate your toolchains, but Gradle is smarter about finding your available JDKs.
* Libraries with type signatures, makes for far easier code reading, and if you pass **kwargs 5 levels down, I hate you. Yes you, sentry-sdk...
* Libraries with correct type signatures, looking at you confluent-kafka, either publish type stubs to typeshed, or update your goddamn doc-string type hints so my IDE doesn't think that confluent_kafka.Message.value() is missing a parameter.
* The ecosystem. I really really really miss the ecosystem of JVM FOSS packages.
* The speed, in general.
I'm sure there's more, but these are the pain points I've been having of late.
Nd it is very compatible with Java itself, interop is dead simple