Java can do "simple" cleanups, where it knows for sure that an object didn't leak from the stack and thus is safe to clean up when the stack is cleaned up. Such escape analysis is also used in other ways, for example to determine whether the lock needs to be taken when you enter a synchronized
block: if the reference is guaranteed to be stack-confined, you don't need to take the lock because there is no risk of any other thread seeing it.
The difference between Java and Rust is that Rust has a strict notion of ownership, so it is possible to know statically when all objects can be cleaned up safely; Java doesn't have this notion, so it has to, in general, rely on the GC to work it out.
So, essentially, no, Java can't do without a GC, because that is how the language was designed; Rust can do without a GC because that is how that language was designed.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…