Java is one of the garbage-collected languages, and the advantage is that developers do not have to deliberately manage memory allocations , reducing the application due to local failures (segmentation fault) causing crashes, while preventing the memory from not releasing the stack (heap) the possibility of bursting, so the code written out is more secure.
Unfortunately, there is still a lot of logic in Java that can lead to memory leaks (logical leak). If you're not careful, your Android app can easily waste memory that's not released, resulting in an out-of-memory error throw (Out-of-memory,oom).
The general memory leak (traditional leak) is due to the fact that when all references to the object have been disposed, the object is still not disposed. (Translator Note: Cursor
forget to close, etc.)
The reason for the logical memory leak (logical leak) is that when the application no longer needs this object, all references to that object are still not released.
If you hold a strong reference to an object, the garbage collector is unable to reclaim the object in memory.
In Android development, the most prone memory leak problem is the context. Activity, for example Context
, contains a lot of memory references, such as View Hierarchies
and other resources. Once leaked Context
, it also means leaking all the objects it points to. Android machine memory is limited, too much memory leaks easily lead to oom.
Detecting logical memory leaks requires subjective judgment, especially when the life cycle of an object is not clear. Fortunately, with a Activity
clear life cycle, it is easy to spot the cause of the leak. Activity.ondestroy () is considered to be Activity
the end of life, which, in procedural terms, should be destroyed, or the Android system needs to reclaim the memory (the translator notes: Android will reclaim invisible when memory is not enough Activity
).
If this method finishes executing and there is still a strong reference to the activity in the stack, the garbage collector cannot mark it as reclaimed memory, and we are going to recycle it!
The result is Activity
survival beyond its life cycle.
Activity
is a heavyweight object and should be made to the Android system to handle it. However, logical memory leaks are always inadvertently occurring. (Translator Note: An activity has been tried to cause a 20M memory leak). In Android, there are two pitfalls that lead to potential memory leaks:
- The static variable of the global process (Process-global). This ignores the state of the application and holds
Activity
the strong reference to the monster.
Activity
threads that live outside the life cycle. There are no strong references to empty the pair Activity
.
Check that you have encountered the following situation.
Static Activities
A static variable is defined in the class Activity
and the currently running Activity
instance is assigned a value to the static variable.
If this static variable Activity
is not emptied after the end of the life cycle, it causes a memory leak. Because the static variable is the life cycle of the application, the leak Activity
will persist in the application process and will not be reclaimed by the garbage collector.
static activity activity; setstaticactivity() {this ;} View Sabutton = Findviewbyid (R.id.sa_button); Sabutton.setonclicklistener (onClick(View v) {setstaticactivity (); nextactivity ();}});
Memory Leak 1–static activitystatic views
Similar situations occur in singleton mode, and if Activity
used frequently, it is useful to keep an instance in memory. As mentioned earlier, the mandatory extension Activity
of the life cycle is quite dangerous and unnecessary, and cannot be done in any way.
Special case: If a view initialization is resource-intensive and remains constant for a Activity
lifetime, it can be changed to static and loaded into the view tree (view hierachy), such that when Activity
destroyed, resources should be freed. (Translator Note: The sample code does not release memory, this static view is NULL, but it is still not recommended to use this static view method)
static view; Setstaticview() { view = Findviewbyid (R.id.sv_button); } View Svbutton = Findviewbyid (R.id.sv_button); Svbutton.setonclicklistener (onClick(View v) {setstaticview (); nextactivity ();}});
Memory Leak 2–static Viewinner Classes
Continue, assuming that Activity
there is an inner class that can improve readability and encapsulation. will be as we create an inner class, and hold a reference to a static variable, congratulations, the memory leak is not far away from you (translator Note: When the destruction of empty, ah).
static Object inner; createinnerclassnew Innerclass ();} View Icbutton = Findviewbyid (R.id.ic_button); Icbutton.setonclicklistener (onClick(View v) {createinnerclass (); nextactivity ();}});
Memory Leak 3–inner Class
One of the advantages of an inner class is the ability to access an external class, which unfortunately causes a memory leak because the inner class holds a strong reference to the external class instance.
Anonymous Classes
Similarly, anonymous classes maintain references to external classes. So memory leaks are easy to happen when you Activity
define anonymous in theAsyncTsk
。 When an asynchronous task is executed in the background during a time-consuming task, it Activity
is unfortunately destroyed (the translator notes: The user exits, the system recycles), and the AsyncTask
held Activity
instance is not reclaimed by the garbage collector until the asynchronous task ends.
voidStartAsyncTask () {new asynctask<void, Void, void> () {
@Override
protected Void doinbackgroundwhile (true); }}.execute (); } super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); View Aicbutton = Findviewbyid (R.id.at_button); Aicbutton.setonclicklistener (new View.onclicklistener () {@ Override public void onclick
Memory Leak 4–asynctaskhandler
Similarly, the definition is anonymous Runnable
and executed with anonymous classes Handler
. The Runnable
inner class holds an implicit reference to the outer class, is passed to Handler
the message queue MessageQueue
, and the Message
instance is not destroyed until the message is processed, Activity
causing a memory leak.
voidCreatehandler() {New Handler () {@OverridePublicvoidHandlemessage(Message message) { super.handlemessage (message);}}. Postdelayed (new Runnable () { @Override public void Run() {while (true);}, Long.max_va LUE >> 1); } View Hbutton = Findviewbyid (R.id.h_button); Hbutton.setonclicklistener (new View.onclicklistener () { @Override public void OnClick( View v) {createhandler (); nextactivity ();}});
Memory Leak 5–handlerthreads
We are again using thread and timertask to present a memory leak.
void Spawnthread() { new Thread () { @Override public void Run() { C11>while (True);}}. Start (); } View TButton = Findviewbyid (R.id.t_button); Tbutton.setonclicklistener (new View.onclicklistener () { @Override public void OnClick( View v) {spawnthread (); nextactivity ();}});
Memory Leak 6–threadtimertask
As long as an instance of an anonymous class, whether or not on a worker thread, will hold Activity
a reference that causes a memory leak.
voidscheduletimer () {new Timer (). Schedule (new TimerTask () { @Override public void run () {while ( true); }}, Long.max_value >> 1); } View Ttbutton = Findviewbyid (R.id.tt_button); Ttbutton.setonclicklistener (new View.onclicklistener () {@ Override public void onclick
Memory Leak 7–timertasksensor Manager
Finally, the system service can be obtained by context.getsystemservice (int name). These services work in their own processes, helping applications handle background tasks and handle hardware interactions. If you need to use these services, you can register the listener, which causes a reference to be held by the service Context
and can Activity
cause a memory leak if the listeners are not logged off at the time of the destruction.
Registerlistener() { Sensormanager Sensormanager = (sensormanager) getsystemservice (sensor_service); Sensor sensor = Sensormanager.getdefaultsensor (sensor.type_all); Sensormanager.registerlistener (this, sensor, sensormanager.sensor_delay_fastest); } View Smbutton = Findviewbyid (R.id.sm_button); Smbutton.setonclicklistener (onClick(View v) {registerlistener (); nextactivity ();}});
Memory Leak 8–sensor Manager Summary
Seeing so many examples of memory leaks, it's easy to eat up the memory of the phone to make garbage collection processing more frequent, even the worst case can cause oom. Garbage collection is an expensive operation that can cause visible stuttering to the naked eye. So, when instantiating, take note of the chain of references that are held and often do a memory leak check.
Good luck.
"reprinted" 8 possible types of Android memory leaks