This is just a degenerate case of garbage collection, really.
I have simply relied on leaking wildly before, knowing it's a small program that will end soon. It's an acceptable solution in some cases.
But a quick google gets https://openjdk.java.net/jeps/318 which does say
Non-Goals
It is not a goal to introduce manual memory
management features to Java language and/or JVM...
but it doesn't say you can't or shouldn't. Game on then.You're totally right. Rather stupidly I hadn't thought of that.
I suppose it is possible to avoid garbage collection if you are willing to accept kind of old-style programming practices. You could have arrays of objects and when an object is no longer needed you don't deallocate it but allow it to be reused when another object of that kind is needed. I guess this would not lead to clearer code for most purposes. But, who knows, some people have been complaining about the lack of clarity in object oriented code.
[0] https://en.wikipedia.org/wiki/Resource_acquisition_is_initia...
If I adhere to RAII, I guarantee that if I allocate something in a scope then it will be de-allocated when I leave the scope. But if I want to return a closure (a function pointer + state) then I can't de-allocate it myself.
I thing C++ and Rust are trying to address this kind of thing with move semantics and ownership. Perhaps functional languages will solve this kind of thing with linear types in the future.
I'm currently looking into 'defunctionalization', 'lambda lifting', etc. to see if they are viable alternatives.
You can infer where you should allocate data. It was done 25 years ago.
The problem is that for complex programs you end with one big region and this is not useful.
Linear types that are visible to the user will not solve these problems. In fact, they will complicate things greatly, because you have to provide two functions for mapping, for example: for normal and linear types. And their mix with normal types is problematic at best.
The inference of linear operations in the backend, on the other hand, can be more efficient - you may end up using linear memory references not knowing about that.
* It's much faster than malloc/free. a fragmented free is much much slower than a full stop-the-world major GC, and GC allocation is zero cost.
* it makes your program memory safe, memory safety is too hard to be left to the user.
* it makes your program run faster with a compacting collector (but not this trivial one). it does defragmentation, and puts together used arrays/strings, so that they often are on the same cache-line. typically 2x faster.
In a sane program without GC, you'll be freeing the memory when you don't need it any more, and your less talented colleagues will get it wrong.
Then you ruined it all with the last sentence...