How does the JVM handle garbage collection, and how would you troubleshoot a memory leak in a production environment?