How does garbage collection work in Java, and what strategies can you employ to prevent memory leaks in a long-running application?