Home >Common Problem >What are the causes and solutions of memory leaks
The reasons and solutions are: 1. Use static internal classes to avoid memory leaks caused by threads; 2. Use cached convertView to construct Adapter to avoid memory leaks caused by ListView; 3. Before exiting the program, clear Things in the collection are set to null to avoid memory leaks in the collection container.
The operating environment of this tutorial: Windows 7 system, Dell G3 computer.
1. Memory leaks caused by singletons
Due to singleton The static nature of the instance makes its life cycle as long as the life cycle of the application. If an object is no longer needed and the singleton object still holds a reference to the object, the object cannot be recycled normally, resulting in A memory leak occurred.
Example: Prevent instances of memory leaks caused by singletons
// 使用了单例模式 public class AppManager { private static AppManager instance; private Context context; private AppManager(Context context) { this.context = context; } public static AppManager getInstance(Context context) { if (instance != null) { instance = new AppManager(context); } return instance; } }
2. Memory leaks caused by non-static inner classes creating static instances
For example, Sometimes in activities that are started frequently, in order to avoid repeatedly creating the same data resources, the following writing may appear:
public class MainActivity extends AppCompatActivity { private static TestResource mResource = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(mResource == null){ mResource = new TestResource(); } //... } class TestResource { //... } }
3. Memory leak caused by Handler
Example: Create a static object of an anonymous inner class
public class MainActivity extends AppCompatActivity { private final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // ... } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { // ... handler.sendEmptyMessage(0x123); } }); } }
1. From the perspective of Android
When an Android application starts, the main thread of the application will automatically create a Looper object and the MessageQueue associated with it. When a Handler object is instantiated in the main thread, it will automatically be associated with the MessageQueue of the main thread Looper. All Messages sent to the MessageQueue will hold a reference to the Handler, so the Looper will call back the handleMessage() method of the Handle accordingly to process the message. As long as there are unprocessed Messages in the MessageQueue, the Looper will continue to take them out and hand them over to the Handler for processing. In addition, the Looper object of the main thread will accompany the entire life cycle of the application.
2. Java perspective
In Java, non-static inner classes and anonymous inner classes will potentially hold references to the outer classes to which they belong, but static inner classes will not.
Analyze the above example. When MainActivity ends, the unprocessed message holds a reference to the handler, and the handler holds a reference to the external class to which it belongs, which is MainActivity. This reference relationship will remain until the message is processed, which prevents MainActivity from being recycled by the garbage collector, causing a memory leak.
Solution: Separate the Handler class or use a static inner class to avoid memory leaks.
4. Memory leaks caused by threads
Example: AsyncTask and Runnable
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new MyRunnable()).start(); new MyAsyncTask(this).execute(); } class MyAsyncTask extends AsyncTask<Void, Void, Void> { // ... public MyAsyncTask(Context context) { // ... } @Override protected Void doInBackground(Void... params) { // ... return null; } @Override protected void onPostExecute(Void aVoid) { // ... } } class MyRunnable implements Runnable { @Override public void run() { // ... } } }
AsyncTask and Runnable both use anonymous inner classes, then they will Holds an implicit reference to the Activity in which it resides. If the task is not completed before the Activity is destroyed, the Activity's memory resources will not be recycled, causing a memory leak.
Solution: Separate the AsyncTask and Runnable classes or use static inner classes to avoid memory leaks.
5. Memory leaks caused by not closing resources
For resources such as BroadcastReceiver, ContentObserver, File, Cursor, Stream, Bitmap, etc., they should be destroyed in time when the Activity is destroyed Close or log out, otherwise these resources will not be recycled, causing memory leaks.
1) For example, a BraodcastReceiver is registered in the Activity, but the BraodcastReceiver is not unregistered after the Activity ends.
2) Resource objects such as Cursor, Stream, File, etc. often use some buffers. When we are not using them, we should close them in time so that their buffers can reclaim memory in time. Their buffers not only exist within the Java virtual machine, but also exist outside the Java virtual machine. If we just set its references to null without closing them, memory leaks will often occur.
3) When a resource object is not in use, its close() function should be called to close it, and then set to null. We must make sure that our resource objects are closed when our program exits.
4) Call recycle() to release memory when the Bitmap object is no longer in use. Bitmaps after 2.3 should no longer need to be manually recycled, as the memory is already in the Java layer.
6. Memory leak caused when using ListView
Initially ListView will instantiate a certain number of View objects from BaseAdapter according to the current screen layout, and ListView will Cache these View objects. When the ListView is scrolled upward, the View object of the Item originally located at the top will be recycled and then used to construct the Item that appears below. This construction process is completed by the getView() method. The second formal parameter convertView of getView() is the View object of the cached Item (if there is no View object in the cache during initialization, convertView is null).
When constructing the Adapter, the cached convertView is not used.
Solution: Use the cached convertView when constructing the Adapter.
7. Memory leak in collection container
We usually add some object references to a collection container (such as ArrayList). When we don't need the object, we do not clear its references from the collection, so the collection will become larger and larger. If this collection is static, the situation is even more serious.
Solution: Before exiting the program, clear the items in the collection, then set them to null, and then exit the program.
8. Leakage caused by WebView
When we do not use the WebView object, we should call its destroy() function to destroy it and release the memory it occupies. , otherwise the memory it has occupied for a long time cannot be recycled, causing a memory leak.
Solution: Open another process for WebView and communicate with the main thread through AIDL. The process in which WebView is located can choose the appropriate time to destroy according to business needs, thereby achieving complete memory release.
For more computer-related knowledge, please visit the FAQ column!
The above is the detailed content of What are the causes and solutions of memory leaks. For more information, please follow other related articles on the PHP Chinese website!