当前位置:网站首页>Analyzing while experimenting - memory leakage caused by non static inner classes
Analyzing while experimenting - memory leakage caused by non static inner classes
2022-06-11 05:12:00 【Kakar】
Experiment and analysis - Memory leakage caused by non static inner classes
about Java For the programmer , Memory leakage must be a common problem in the development process , There are many situations that can lead to memory leaks , The fundamental problem is Java Memory reclamation manager for (GC) It is impossible to recycle objects that are not in use , This causes the object to persist in memory , The resulting memory leak , The end result is a memory overflow .
stay Android in , because Android The structure and ecology of , The problem has also become relatively easy to attract people's attention , You must often listen to experienced people Android Development colleagues say this sentence :“ Non static inner classes hold references to outer classes , Attention should be paid to memory leakage when using ”.
I heard that , We should analyze it by ourselves , How to understand ? Why? ? And doubt its correctness , After all, only in this way can I improve , So we take this as a breakthrough , Let's analyze this sentence first .
First, how to understand this sentence , There are several key words in this sentence , The static 、 Inner class 、 hold 、 External class ,
From non static and inner classes, we know that we must define a non static inner class , Consider the following code
public class MainActivity2 extends AppCompatActivity {
private MessageCall messageCall;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
messageCall = new MessageCall();
findViewById(R.id.doSomething).setOnClickListener(view -> {
messageCall.doSomething();
});
}
class MessageCall {
public void doSomething(){
System.out.println("doSomething");
}
}
}
For the convenience of checking the memory leakage , We use leakcanary To monitor our memory , Run the program , Click button , Then press the back button , Return to desktop , You'll find that , No memory leaks ,WHY? The static , The inner classes all meet .
So does it hold references to external classes ? Let's take a look Bytecode You can see ( It can be downloaded from Build -> Analyze APK -> Choose the appropriate dex -> Find... Under the package name MainActivity2 Of Class -> Right click Show Bytecode see )
You can see onCreate In the method, we new-instance 了 MainActivity2$ MessageCall, And in init When it came to our MainActivity2, See here we might as well have a look MainActivity2$MessageCall This class
there this$0 In fact, that is MainActivity2, therefore MessageCall Hold on to MainActivity2 References to .
That's again WHY?WHY? Will not cause memory leaks ?
In fact, non static inner classes hold references to outer classes , It is not an absolute condition that memory leaks will occur , There is another condition , That is, the life cycle of the inner class is longer than that of the outer class , Memory leakage will occur .
Let's try it in the just doSomething In the method , Add a thread , Let it run in the background 20 second
class MessageCall {
public void doSomething(){
Runnable work = new Runnable() {
@Override public void run() {
System.out.println("doSomething start");
SystemClock.sleep(20000);
System.out.println("doSomething end");
}
};
new Thread(work).start();
}
}
Let's run the program again , Click button , Then press the back button , Return to desktop , This time, there was a memory leak 
It can be seen that ,MainActivity2 destory, however MessageCall Of this$0 Leakage and MessageCall It's because MessageCall$1.this$1 The real source of leakage is Thread-4, You can check the bytecode by yourself , You can find Thread In fact, it also holds an external class MessageCall Referenced by , So it led to a chain reaction ,Thread- -> MessageCall -> MainActivity2.
that , What can we do to solve this problem ? There is a very simple solution , It must be known to all , That is to use static inner classes , That's all right. , In this way, the life cycle of the inner class is not directly related to the life cycle of the outer class , When the outer class destory When , Static inner classes are not affected , Naturally, there is no memory leak .
We analyze and solve the problem here , In fact, those who have done so will certainly find that there are still some problems in the actual operation ,
The most important problem is using static inner classes , You can't directly reference some member variables of an external class , This makes the code feel complicated , that , What else can we do ?
In fact, in this case , There is also a very clever technique in it , That's using lambda, Let's take a look at this method , Change the code
class MessageCall {
public void doSomething(){
Runnable work = () -> {
System.out.println("doSomething start");
SystemClock.sleep(20000);
System.out.println("doSomething end");
};
new Thread(work).start();
}
}
Run the program and you will find , No memory overflow occurred 
Let's look at what happens to bytecode ? We see directly MainActivity2$MessageCall Bytecode in , It mainly depends on doSomething Method 
You can see here that there will be lambda, Let's see lambda

Found that its internal call MessageCall A static method in is called lambda$doSomething, go back to MessageCall In bytecode , Found this static method , You must know the reason when you see here , Because this is a static method , So it will not lead to holding MessageCall References to , This will not lead to MessageCall Held in MainActivity References to will not be released , Played a series of chain effects , This is it. lambda The magic of .
But don't be happy too soon , Because it doesn't mean lambda Just a matter of , All we use is lambda One of the , be called Non-instance-capturing lambdas, That means we are lambda No external instance is used in the method , Contrary , Of course, there is another , Namely Instance-capturing lambdas, That is, kidnapping an external instance lambda, Let's see , If we were MainActivity It defines a int The value of the type is 0, And then in run Of lambda In the thread, let this value be re assigned to 1
private Integer i = 0;
class MessageCall {
public void doSomething(){
Runnable work = () -> {
System.out.println("doSomething start");
i = 1;
SystemClock.sleep(20000);
System.out.println("doSomething end");
};
new Thread(work).start();
}
}
So let's run it again , Will find , Still memory overflow , So let's look at bytecode , After the previous analysis , We directly located MessageCall In bytecode doSomething Method 
It is not found that static 了 , therefore , Of course, it will be similar to what we didn't use before lambda It's written the same way , out of memory .
In conclusion , On the premise that the life cycle of the inner class is longer than that of the outer class :
1. Don't use lambda, Non static class , Methods do not use external instances , Memory leaks can result
2. Don't use lambda, Non static class , Use external instances inside methods , Memory leaks can result
3. Use lambda, Non static class , Methods do not use external instances , No memory leaks
4. Use lambda, Non static class , Use external instances inside methods , Memory leaks can result
5. Static class , Will not cause memory overflow
Such a conclusion , Are you right lambda It's a step closer to understanding .
边栏推荐
- Zed2 running vins-mono preliminary test
- New product release: Lianrui launched a dual port 10 Gigabit bypass network card
- Oh my Zsh correct installation posture
- [NIPS2021]MLP-Mixer: An all-MLP Architecture for Vision
- Dongmingzhu said that "Gree mobile phones are no worse than apple". Where is the confidence?
- (十五)红外通信
- 华为设备配置通过GRE隧道接入虚拟专用网
- Intercept file extension
- The programmers of a large factory after 95 were dissatisfied with the department leaders, and were sentenced for deleting the database and running away
- 工具类ObjectUtil常用的方法
猜你喜欢

点击图标不灵敏咋整?

Network security construction in 5g Era

Conversion relationship between coordinate systems (ECEF, LLA, ENU)

Carrier coordinate system inertial coordinate system world coordinate system

Huawei equipment is configured with cross domain virtual private network

English digital converter

2021 iccv paper sharing - occlusion boundary detection

BP neural network derivation + Example

高斯白噪声(white Gaussian noise,WGN)

1.使用阿里云对象OSS(初级)
随机推荐
What is the difference between a wired network card and a wireless network card?
Detailed explanation of network security bypass network card
NVIDIA SMI has failed because it could't communicate with the NVIDIA driver
Introduction to coordinate system in navigation system
Thesis 𞓜 jointly pre training transformers on unpaired images and text
2021-04-19
How to apply for free idea with official documents
35.搜索插入位置
Conversion relationship between coordinate systems (ECEF, LLA, ENU)
力扣(LeetCode)161. 相隔为 1 的编辑距离(2022.06.10)
Emnlp2021 𞓜 a small number of data relation extraction papers of deepblueai team were hired
Iris dataset - Introduction to machine learning
Zed2 camera calibration -- binocular, IMU, joint calibration
Technology | image motion drive interpretation of first order motion model
Share | guide language image pre training to achieve unified visual language understanding and generation
Deep extension technology: intelligent OCR recognition technology based on deep learning has great potential
使用acme.sh自动申请免费SSL证书
What is a smart network card? What is the function of the smart network card?
Preliminary test of running vins-fusion with zed2 binocular camera
6 questions to ask when selecting a digital asset custodian