閱讀的文章:Android GC 原理探究
下面補充一些備注和筆記。
算法
復制算法 (Copying)圖示:
這里寫圖片描述
標記-壓縮算法 (Mark-Compact)英文描述:
mark-compact
總結起來就是
標記 —> 壓縮有用的對象到一端 —> 回收此端外剩下的空間
圖示:
這里寫圖片描述
可以看出,這兩種算法都可以減少內存碎片
GC Roots
英文官方說明:
The root kinds are:
- Class - class loaded by system class loader. Such classes can never be unloaded. They can hold objects via static fields. Please note that classes loaded by custom class loaders are not roots, unless corresponding instances of java.lang.Class happen to be roots of other kind(s).
- Thread - live thread
- Stack Local - local variable or parameter of Java method
- JNI Local - local variable or parameter of JNI method
- JNI Global - global JNI reference
- Monitor Used - objects used as a monitor for synchronization
- Held by JVM - objects held from garbage collection by JVM for its purposes. Actually the list of such objects depends on JVM implementation. Possible known cases are: the system class loader, a few important exception classes which the JVM knows about, a few pre-allocated objects for exception handling, and custom class loaders when they are in the process of loading classes. Unfortunately, JVM provides absolutely no additional detail for such objects. Thus it is up to the analyst to decide to which case a certain "Held by JVM" belongs.
If an object is a root, it is specially marked in all views showing individual objects.
中文
為什么GC會引起應用暫停(STW Stop The World)
因為gc需要確保標記準確無誤,所以不可能一邊標記,一邊還有創建和銷毀對象的活動,只能是暫定所有線程,等標記和清理完成后恢復所有線程。
弱引用(soft reference)
可以應用到安卓開發中的tips
- 我們首先要盡量避免掉頻繁生成很多臨時小變量(比如說:getView,onDraw等函數),以減少gc頻率和內存碎片。
另外,又要盡量去避免產生很多長生命周期的大對象,減少老年代執行gc的次數。 Old GC的速度一般會比Young gc慢10倍以上。并且執行"標記-壓縮算法",標記和壓縮階段都會暫停應用,造成較長時間的STW。
(復制算法是用空間換時間,標記-壓縮算法是用時間換空間)
- 也可以注冊一個應用不可見(比如鎖屏,被放到后臺)的生命周期回調,主動觸發gc, 因為反正應用不可見,GC 下以便之后運行更流暢,不過只是設想,還沒實驗。
- 作者也說了,本來想故意“生成一些幾百K的對象,試圖去擴大可用堆大小的時候,反而會導致頻繁的GC,因為這些對象的分配會導致GC,而GC后會讓堆內存回到合適的比例,而我們使用的局部變量很快會被回收理論上存活對象還是那么多,我們的堆大小也會縮減回來無法達到擴充的目的”此路不通。