How do you optimize memory management and avoid memory leaks in a garbage-collected language such as Java?