What is memory leakage?
First we need to define what memory leakage is.
Technically Java can not have leaks if considering that the leak only occurs when something is allocated and never occurs the possibility of release when there are no more references to this object.
If you consider that leaking is all memory occupied without having a reference to that object, then Java leaks memory all the time. Only it will not have leaked memory when the GC runs and clear all that there are no more references. Soon after it starts leaking again. If you do not consider this a leak, we still have the definition that Java never leaks memory.
If you consider leakage is when you have a referenced object still somewhere, but this object will no longer be used in the application, then leakage occurs and may be for several reasons. But many people do not consider this leak since the object is referenced.
Forms of leakage
An object can continue to be referenced without use if it is attached to a static variable directly or indirectly (see below). But if you’ve defined that he’s static, that’s probably what you want, isn’t it? If it isn’t, you made a mistake, but I wouldn’t call it a memory leak, it’s a misguided engineering.
If an object is attached to an instance and that instance for some reason never dies, then the reference to it never dies either. Some people say it’s memory leakage, I keep thinking it’s engineering error, if it’s not a real need, and if it’s a need, then it’s okay.
If you have a method in a thread running in parallel and it is running all the time, and in this method has a local variable that references an object that is no longer used after some operation. It would be a memory leak?
Actually with threads has a lot of situation that it is easy to keep references longer than you want.
When does interning of string is like having a static object.
When you open a resource and it doesn’t close, the object is allocated in unmanaged memory and is there without collection. That’s why it is recommended to always open with try-resource
. This would clearly be a leak, but the GC can handle it if there are no references.
When you make a pool of objects you may be holding other objects referenced there. That is, an object in the pool is no longer in use, but he is alive, and all that is attached to him and also serves no purpose for anything else is still alive. It might be considered memory leakage, but I still think it’s engineering error, or normal mechanism behavior.
Something similar may occur with cache, but is more rare. Properly cached has weak references, so its release can occur easily.
Use sun.misc.Unsafe
you may have a leak, after all it allows you to access the memory in an unmanaged way.
There is a list of algorithms that holds a reference where it should not, but you do not want to list several examples here, right?
In general this occurs when you take an element of a array or a class and thinks you’re copying it, when you’re actually referencing the element. Then you may no longer have any reference to the tip of array huge, but still has a reference to an element of it. The array cannot be released. Technically this is not memory leak, but the effect is very similar. The right one is to copy the contents of the reference.
That goes for any kind of array, including String
. A simple and seemingly harmless substring()
can hold a reference longer than you want. You carry a book, make a substring()
in a word and ready, the book can no longer be released until the variable holding that word is released, even if nothing else references the book (it seems that this no longer occurs in recent versions, but it has created other new problems).
In Java this is mostly because almost everything is reference (this will start to change in Java 10).
What is consumed by the JVM itself and is not released, can be considered memory leakage?
Nor will I speak of those corner cases that can occur in a very forced way, practically exploiting a gap that is even difficult to reproduce.
How to solve
There are cases where you need to manually override a variable to release the reference, but I usually say that if you did this there is probably something wrong with the code. There may be some reason to do so, but almost always it is gambiarra.
In general it is necessary to know the language well, the libraries you are using and be attentive to what you are doing. Contrary to what many people regret, GC does not eliminate the need to think about memory management.
Releasing memory is not your concern, releasing references remains your responsibility. It will not go away giving null
everywhere.
Decrease the amount of allocations is still interesting to have a more efficient application and Java has finally started taking this path.
Have any answers solved what was in doubt? Do you need something else to be improved? Do you think it is possible to accept it now?
– Maniero