What you need to know first
1. C/C++ programmers manage memory by themselves, while Java memory is automatically reclaimed by the GC.
Although I'm not very familiar with C++, I probably didn't make a common sense mistake in this.
2. What is a memory leak?
A memory leak refers to the existence of memory in the system that cannot be recycled, sometimes causing insufficient memory or system crash.
In C/C++, memory leaks occur when allocated memory is not released.
3. There is a memory leak in Java. We must admit this first before we can continue to discuss it. Although Java has memory leaks, you basically don't need to care about it, especially those who are not particular about the code itself.
Memory leaks in Java certainly mean: there are useless objects that cannot be recycled by the garbage collector.
And even if there is a memory leak problem, it may not show up.
4. Parameters in Java are all passed by value.
There is basically no objection to basic types, but we cannot have any objection to reference types.
Java memory leaks
1. Heap memory overflow (outOfMemoryError: java heap space)
In the JVM specification, the memory in the heap is used to generate object instances and arrays.
If subdivided, the heap memory can also be divided into the young generation and the old generation. The young generation includes an eden area and two survivor areas.
When a new object is generated, the memory application process is as follows:
a. The jvm first tries to allocate the memory required for the new object in the eden area;
b. If the memory size is sufficient, the application ends, otherwise the next step is;
c. JVM starts youngGC and tries to release inactive objects in the Eden area. After release, if the Eden space is still not enough to put new objects, it tries to put some of the active objects in Eden into the Survivor area;
d. The Survivor area is used as the intermediate exchange area between Eden and old. When the OLD area has enough space, the objects in the Survivor area will be moved to the Old area, otherwise they will be retained in the Survivor area;
e. When there is not enough space in the OLD area, the JVM will perform full GC in the OLD area;
f. After full GC, if the Survivor and OLD areas still cannot store some objects copied from Eden, causing the JVM to be unable to create a memory area for new objects in the Eden area, an "out of memory error" will appear:
outOfMemoryError:java heap space
2. Memory overflow in method area (outOfMemoryError: permgem space)
In the JVM specification, the method area mainly stores class information, constants, static variables, etc.
Therefore, if the program loads too many classes, or uses dynamic proxy generation technology such as reflection or gclib, it may cause a memory overflow in this area. Generally, the error message when a memory overflow occurs in this area is:
outOfMemoryError:permgem space
3. Thread stack overflow (java.lang.StackOverflowError)
The thread stack is a memory structure unique to the thread, so problems with the thread stack must be errors generated when a thread is running.
Generally, thread stack overflow is caused by too deep recursion or too many levels of method calls.
The error message when a stack overflow occurs is:
java. lang. StackOverflowError
Several scenarios of memory leaks:
1. Long-lived objects hold references to short-lived objects.
This is the most common scenario of memory leaks and a common problem in code design.
For example: if local variables are cached in a global static map and there is no clearing operation, the map will become larger and larger over time, causing memory leaks.
2. Modify the parameter value of the object in hashset, and the parameter is the field used to calculate the hash value.
After an object is stored in the HashSet collection, the fields in the object that participate in calculating the hash value cannot be modified, otherwise the modified hash value of the object will be different from the hash value when it was originally stored in the HashSet collection. , in this case, even if the contains method uses the current reference of the object as a parameter to retrieve the object from the HashSet collection, it will return the result that the object cannot be found, which will also result in the failure to delete the current object from the HashSet collection, causing Memory leak.
3. Set the number of connections and shutdown time of the machine
Opening a very resource-intensive connection for a long time can also cause memory leaks.
Let’s look at an example of a memory leak:
public class Stack { private Object[] elements=new Object[10]; private int size = 0; public void push(Object e){ ensureCapacity(); elements[size++] = e; } public Object pop(){ if( size == 0) throw new EmptyStackException(); return elements[--size]; } private void ensureCapacity(){ if(elements.length == size){ Object[] oldElements = elements; elements = new Object[2 * elements. length+1]; System. arraycopy(oldElements,0, elements, 0, size); } }}
The above principle should be very simple. If 10 elements are added to the stack and then all are popped out, although the stack is empty and there is nothing we want, this object cannot be recycled. This meets the two requirements of memory leaks. Condition: Useless, cannot be recycled.
But even the existence of such a thing may not necessarily lead to any consequences. If this stack is used less,
It's just a waste of a few K of memory. Anyway, our memory is already up to G, so what impact will it have? Besides, this thing will be recycled soon, so what does it matter? Let’s look at two examples below.
Example 1
public class Bad{ public static Stack s=Stack(); static{ s. push(new Object()); s. pop(); //There is a memory leak in an object here. push(new Object()); //The above object can be recycled, which is equivalent to self-healing}}
Because it is static, it will exist until the program exits, but we can also see that it has a self-healing function.
That is to say, if your Stack has at most 100 objects, then only 100 objects at most cannot be recycled. In fact, this should be easy to understand. Stack holds 100 references internally. The worst case scenario is that they are all useless, because Once we put new progress, the previous references will naturally disappear!
Example 2
public class NotTooBad{ public void doSomething(){ Stack s=new Stack(); s. push(new Object()); //other code s. pop();//This also results in the object being unable to be recycled and memory leaking. }//Exit the method, s is automatically invalid, s can be recycled, and the references inside the Stack are naturally gone, so //Self-healing can also be done here, and it can be said that this method does not have a memory leak problem, but it will be handed in later// It is only given to GC, because it is closed and not open to the outside world. You can say the above Code 99. 9999% of // situations will not have any impact. Of course, if you write such code, it will not have any bad effects, but // it can definitely be said to be garbage code! There is no contradiction, I will add one in it An empty for loop won't have any big impact, right? Would you do this?}
The above two examples are just trivial, but memory leaks in C/C++ are not Bad, but Worst.
If they are not recycled in one place, they will never be able to be recycled. If you call this method frequently, the memory will be used up!
Because Java also has a self-healing function (I named it myself and haven’t applied for a patent yet), Java’s memory leak problem can be almost ignored, but those who know it should not commit it.
In order to avoid memory leaks, you can refer to the following suggestions when writing code:
1. Release references to useless objects as early as possible;
2. Use string processing, avoid using String, and use StringBuffer extensively. Each String object must occupy an independent area of memory;
3. Use static variables as little as possible, because static variables are stored in the permanent generation (method area), and the permanent generation basically does not participate in garbage collection;
4. Avoid creating objects in loops;
5. Opening large files or taking too much data from the database at one time can easily cause memory overflow, so in these places, you should roughly calculate the maximum amount of data, and set the minimum and maximum memory space values required.