IL2Cpp深坑之WeakReference

年前用WeakReference優化了下Object Cache,Object緩存時如果顯式指定緩存則將其加入到強引用容器中,否則加入到WeakReference容器中,這樣等GC的時候可以清除掉不再使用的Object,安卓Mono下用了好長時間沒有發現問題。今天用IL2Cpp打包iOS卻發現weakReference.IsAlive即使爲true也會出現target被回收的情況,猜測IsAlive在Mono上有問題,後來Google一下,發現十年來大家都在吐槽WeakReference的IsAlive屬性:

Don‘t trust weakreference isalive if it returns true

The WeakReference.IsAlive method can tell you if a particular object is still alive, i.e. it has not yet been garbage collected.  However, when IsAlive returns true, you can’t then necessarily interact with the object through its weak reference, because it could be garbage collected before you get a chance to use it.

For example:

WeakReference dogRef = new WeakReference(dog);
 
// Later, try to ref original Dog
 
if (dogRef.IsAlive)
{
    // Oops - garbage collection on original Dog could occur here
    ((Dog)dogRef.Target).Bark();
}
You can trust IsAlive when it returns false, since a garbage collected object is not in danger of being reconstituted.  But the correct pattern for checking to see if an object is still alive is:

WeakReference dogRef = new WeakReference(dog);
 
// Later, try to ref original Dog
 
Dog origDog = (Dog)dogRef.Target;
if (origDog != null)
{
    origDog.Bark();
}

很明顯,IL2Cpp編譯後開啓了多線程,判定IsAlive之後如果觸發GC,Target就會被回收掉造成NullReferenceException。。。

希望il2cpp團隊能夠改進這一bug,今後要使用一些其他C#原生語法特性時也要考慮多線程帶來的問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章