說說 記憶體洩漏
記憶體洩漏和記憶體溢位是兩個概念。
記憶體洩漏,指的是程式使用過的記憶體“忘記”歸還給系統,造成長時間無謂地佔用。
記憶體溢位,指的是記憶體被大量的使用後,程式再次去申請記憶體時,系統已經不能滿足其要求的情況。
所以,記憶體洩露到一定程度就會導致記憶體溢位。
Java中,記憶體的回收工作是GC來做的。GC也有軟肋:如果持有物件的強引用,GC是無法在記憶體中回收這個物件的。
繞個遠說說幾種引用:
- 強引用(StrongReference)
強引用是使用最普遍的引用。如果一個物件具有強引用,那垃圾回收器絕不會回收它。當記憶體空間不足,Java虛擬機器寧願丟擲OutOfMemoryError錯誤,使程式異常終止,也不會靠隨意回收具有強引用的物件來解決記憶體不足的問題。 - 軟引用(SoftReference)
如果一個物件只具有軟引用,則記憶體空間足夠,垃圾回收器就不會回收它;如果記憶體空間不足了,就會回收這些物件的記憶體。 - 弱引用(WeakReference)
GC掃描過程中,一旦發現了只具有弱引用的物件,不管當前記憶體空間足夠與否,都會回收它的記憶體。 - 虛引用(PhantomReference)
如果一個物件僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。
列舉經常造成記憶體洩漏的幾種情況:
- static變數
- static activity
public class MyActivity extends BaseActivity {
static Activity mActivity = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = this;
}
}
通常,一個activity物件包含了大量的引用,如果賦值給一個靜態變數會使activity脫離系統的管理。被洩漏的activity物件會一直存活在記憶體中,造成記憶體洩漏。
- static view
public class MyActivity extends BaseActivity {
static TextView textView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = new TextView(this);
}
}
- 內部類
內部類使用起來是比較便捷的,但就是這麼一點福利也要冒著記憶體洩漏的風險,因為非靜態的內部類會持有外部類的一個隱式引用。
- Thread
public class MyActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
doSth();
}
private void doSth() {
new Thread() {
@Override
public void run() {
while (true) {
SystemClock.sleep(1000);
}
}
}.start();
}
}
假如新執行緒執行的任務非常耗時,十天半個月都做不完。在此期間,外部類物件也不能被回收。TimerTask和AsyncTask也會有同樣的問題。
- Handler
public class MyActivity extends BaseActivity {
Handler mHanlder = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
doSth();
}
private void doSth() {
mHanlder.postDelayed(new Runnable() {
@Override
public void run() {
}
}, Long.MAX_VALUE >> 1);
}
}
Runnable會持有外部類引用,造成記憶體洩漏。
- Sensor Manager
通過Context.getSystemService(int name)可以獲取系統服務。這些服務工作在各自的程式中,幫助應用處理後臺任務,處理硬體互動。如果需要使用這些服務,可以註冊監聽器,這會導致服務持有了Context的引用,如果在Activity銷燬的時候沒有登出這些監聽器,會導致記憶體洩漏。
public class MyActivity extends BaseActivity implements SensorEventListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerListener();
}
void registerListener() {
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
}
@Override
public void onSensorChanged(SensorEvent event) {
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
恩,就醬。
相關文章
- 分析記憶體洩漏和goroutine洩漏記憶體Go
- js記憶體洩漏JS記憶體
- Android記憶體洩漏Android記憶體
- Android 記憶體洩漏Android記憶體
- jvm 記憶體洩漏JVM記憶體
- Java記憶體洩漏Java記憶體
- 記憶體洩漏的原因記憶體
- valgrind 記憶體洩漏分析記憶體
- 【記憶體洩漏和記憶體溢位】JavaScript之深入淺出理解記憶體洩漏和記憶體溢位記憶體溢位JavaScript
- JVM——記憶體洩漏與記憶體溢位JVM記憶體溢位
- iOS檢測記憶體洩漏iOS記憶體
- Android記憶體洩漏場景Android記憶體
- ThreadLocal記憶體洩漏問題thread記憶體
- PHP 記憶體洩漏分析定位PHP記憶體
- 記憶體洩漏除錯工具記憶體除錯
- ThreadLocal真會記憶體洩漏?thread記憶體
- WebView引起的記憶體洩漏WebView記憶體
- Perfdog 玩轉記憶體洩漏記憶體
- JavaScript之記憶體洩漏【四】JavaScript記憶體
- .Net程式記憶體洩漏解析記憶體
- 記憶體的分配與釋放,記憶體洩漏記憶體
- 1.記憶體優化(一)記憶體洩漏記憶體優化
- JavaScript之記憶體溢位和記憶體洩漏JavaScript記憶體溢位
- 納尼,Java 存在記憶體洩洩洩洩洩洩漏嗎?Java記憶體
- 對 精緻碼農大佬 說的 Task.Run 會存在 記憶體洩漏 的思考記憶體
- Java棧溢位|記憶體洩漏|記憶體溢位Java記憶體溢位
- [Java基礎]記憶體洩漏和記憶體溢位Java記憶體溢位
- 解決記憶體洩漏(1)-ApacheKylin InternalThreadLocalMap洩漏問題分析記憶體Apachethread
- Andriod專案記憶體洩漏流程記憶體
- Java記憶體洩漏解決之道Java記憶體
- Android備忘錄《記憶體洩漏》Android記憶體
- 小心遞迴中記憶體洩漏遞迴記憶體
- vue使用中的記憶體洩漏Vue記憶體
- Android中的記憶體洩漏模式Android記憶體模式
- [譯] Swift 中的記憶體洩漏Swift記憶體
- linux程式之記憶體洩漏分析Linux記憶體
- Android中常見的記憶體洩漏Android記憶體
- Swift的ARC和記憶體洩漏Swift記憶體
- 初步探究Android記憶體洩漏(1)Android記憶體