The other day I was asked how much I knew about Java garbage collection. I am not a performance guru, so I admitted that I knew very little, basically only that it works. As the conversation continued, I realized that while I did not know much about the internals of the garbage collection mechanism, I did know a few things what it did.
First, a quick refresher on how garbage collection works in theory. You continuously create objects in Java, but at some point the memory needs to be cleaned up. Generally, if you create objects within a method, those objects may be garbage collected when the method has completed. Another important point is that if you keep passing objects around to various other classes and methods, those objects will only be garbage collected when there are no longer any references to them. Sometimes the garbage collector will clean more aggressively if you start using large amounts of memory as well. Granted, this is a simplification of the way garbage collection really works, but it gives us some basic ideas on how to keep your java application running smoothly without those weird OutOfMemory errors.
Do not create a lot of objects. This sounds silly, but a surprising number of issues can be resolved by limiting the number of objects that get created. Think of it a different way. If we have a reporting application, are you going to create objects for every row of data in a report? If your application has a lot of reports each having thousands of rows, that is a lot of objects to create.
Create objects only when you need them. If you do need to hold onto a lot of data, does it make sense to create thousands of objects? Can you just pass around a list of ids or a small hashmap? This is similar to the concepts of lazy loading data from a database when you are dealing with persistence frameworks. Why load an entire object when just the id will suffice?
Close all files and streams. This is probably one of the most common issues when it comes to memory management in Java. Sometimes you just miss closing the file because you are more concerned with the contents of the file. There are also times when your error handling takes a different path than the normal code and thus the file stays open. Just remember, finally is your friend.
Do you copy lists or pass lists? This is a harder problem to deal with. If your lists are long and filled with large objects, you may want to avoid the overhead of copying the data in the list. However, if you continuously pass lists around, you are maintaining several references to the objects in that list. This could mean that those objects will not be garbage collected.
These are just some simple tips for clean memory management. In some cases, these issues are easy to avoid. In other cases, the amount of cleanup you need to do is rather annoying and easy to skip. A lot of frameworks, like Spring, will do a lot of the basic cleanup for you, especially in the areas of persistence. The real key is to keep this as simple as possible and to clean up as you go. Just because Java has automatic garbage collection does not mean you should make more trash.