当前位置:网站首页>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 .
边栏推荐
- Google drive download failed, network error
- Technical dry goods: how to select the most suitable RDMA network card
- Vins fusion GPS fusion part
- QT Road (1) -- Introduction to pro file
- Unzip Imagenet after downloading
- Use of mmdetection
- Topological sorting
- Yolov5 training personal data set summary
- Pytoch machine learning GPU usage (conversion from CPU to GPU)
- Detailed explanation of network security bypass network card
猜你喜欢

Cascade EF gan: local focus progressive facial expression editing

Thesis 𞓜 jointly pre training transformers on unpaired images and text

New product pre-sale: 25g optical network card based on Intel 800 series is coming

Zed2 camera manual

Inventory | ICLR 2022 migration learning, visual transformer article summary

Top 100 video information of station B

【入门级基础】Node基础知识总结

Support vector machine -svm+ source code

Differences between the four MQ

Sealem finance builds Web3 decentralized financial platform infrastructure
随机推荐
Lianrui: how to rationally see the independent R & D of domestic CPU and the development of domestic hardware
1.使用阿里云对象OSS(初级)
How to apply for free idea with official documents
The central rural work conference has released important signals. Ten ways for AI technology to help agriculture can be expected in the future
Restoration of binary tree -- number restoration
Intercept file extension
华为设备配置MCE
JVM tuning 6: GC log analysis and constant pool explanation
华为设备配置本地虚拟专用网互访
Tightly coupled laser vision inertial navigation slam system: paper notes_ S2D. 66_ ICRA_ 2021_ LVI-SAM
NVIDIA SMI has failed because it could't communicate with the NVIDIA driver
Use of mmdetection
华为设备配置通过GRE接入虚拟专用网
Deep search + backtracking
Opencv learning path (2-3) -- Deep parsing imshow function
Section V: Recycling Application of asphalt pavement materials
(十五)红外通信
[markdown syntax advanced] make your blog more exciting (III: common icon templates)
Section II: structural composition characteristics of asphalt pavement (2) structural layer and performance requirements
董明珠称“格力手机做得不比苹果差”哪里来的底气?