I agree with you, but I do want to point out one thing: there exists a happy medium between unsafe, no-overhead manual memory management (C++) and safe, GC'd managed memory (Java). For example, unique pointers in Rust enforce compile-time memory safety, without imposing any runtime overhead whatsoever and without forcing the programmer to manually allocate and free. In other words, there does exist such a thing as safe, no-overhead, automatic memory management, if you're willing to accept the single-ownership restriction of linear types (which in practice doesn't seem very onerous at all).
Yes, it's easier to write safe applications in a managed language, but it comes at a performance price due to the GC.
It's far easier to write an app in C++ that performs well. There's no overhead of a virtual machine (there goes the safety...) and manual memory management tends to also yield better results in terms of footprint and CPU time when done properly. C++ gives you the tools to implement a fast process with a small memory footprint; managed languages do not unless they're using a null GC! C++ also gives you the tools tools to write a sloppy heap of shit, but then again, Java affords such a facility too!!
Garbage collection simply isn't free. Maintaining the lie that a system has infinite memory comes with a price.
I'm not making the point that GC is evil, and I write code in managed languages frequently, but I am making the point that it's really only appropriate for situations in which you're paying for the hardware, and using a managed language makes good business sense.