How does garbage collection work in Java, and how do you identify a memory leak in a running application?