0

I'm facing a strange problem I don't know even how to properly explain, but I hope somebody has faced this pseudo-problem and can tell me more or less why it happens.

I have a complex activity that occassionally spans threads to load resources.

It looks like that, somehow, if I assign a weakreference in the execution context of one thread, later on, on the UI thread, it returns null.

I'm absolutely sure I don't null that reference, as I only assign it on one place, that is like:

function assignReference(FunqSlide slide) {

    mWeakEditSlide=new WeakReference<FunqSlide>(newSlide);
    if (Conf.LOG_ON) Log.d(TAG, "SetSlide_internal "+index+"="+mWeakEditSlide+"->"+mWeakEditSlide.get());
    .
    .
}

And this produces the trace with the expected weakreference assigned to a valid object

    06-01 17:40:50.030: D/FunqStory[Hiphop en LA](18390): SetSlide_internal 4=java.lang.ref.WeakReference@41625d18->FunqSlide{40f60728}
    .
    . next is processing 

But the program flow continues and, slightly later on, a function accesses the previously created reference, but it is null!!!

    06-01 17:40:53.330: D/FunqStory[Hiphop en LA](18390): *** CURRENT EDIT SLIDE ID weakreference is null!!!

    06-01 17:40:53.330: E/AndroidRuntime(18390): FATAL EXCEPTION: main
    06-01 17:40:53.330: E/AndroidRuntime(18390): java.lang.NullPointerException
    06-01 17:40:53.330: E/AndroidRuntime(18390):    at com.regaliz.funq.gui.Props_LayerList.loadSlide(Props_LayerList.java:77)
    06-01 17:40:53.330: E/AndroidRuntime(18390):    at com.regaliz.gui.fragments.FunqHelperSupport$Frag.setup_native_pane(FunqHelperSupport.java:1028)
    06-01 17:40:53.330: E/AndroidRuntime(18390):    at com.regaliz.libneo.NativeStory$ActionBarHandler.handleItemSelected(NativeStory.java:1612)

And, if had nulled it, there should be a debug trace of the function assignRefennce before the nullpointerexception, but there isn't, what indicates that something outside my code is nulling the reference for me.

Of course I've solved it just doing the stuff in the same thread, but I'd really want to know what's going on!

Any pointers? or WeakReferences? xD

Thanks in advance !

rupps
  • 9,712
  • 4
  • 55
  • 95
  • Out of curiosity, why are you using a WeakReference at all? – Karakuri Jun 01 '13 at 16:12
  • They point to fragments that are recreated under different circumstances, like rotating screen, unfocusing the activity, spawning child activities, etc... and I want to explicitly destroy them in those cases, unbind their bitmaps, etc ... because they are really heavy objects with a lot of bitmaps inside. It really helps a lot to use weakreferences so everything can be GC'ed quickly and leaves a lot of memory for the child activities. And on top of it all, these fragments are inside a ViewPager ... – rupps Jun 01 '13 at 16:16
  • What exactly is null, mWeakEditSlide itself or the result of mWeakEditSlide.get()? – Michael Butscher Jun 01 '13 at 16:18
  • mWeakEditSlide !!!! isn't it strange???? – rupps Jun 01 '13 at 16:19

1 Answers1

0

Are you trying to read the WeakReference from a different thread than the one that created it? If you then you need to use proper synchronization so that the change is visible.

zienkikk
  • 2,404
  • 1
  • 21
  • 28
  • yes sir! When I do it from a different thread is when it crashes... So should I synchronize on the object or on the weakreference in your opinion? BTW-- it crashes like 3 seconds after I assign it. Is it possible it is not yet visible without synchronization? – rupps Jun 01 '13 at 16:34
  • @rupps Try to declare mWeakEditSlide as volatile – Michael Butscher Jun 01 '13 at 16:36
  • @Michael just tried volatile and transient , didnt' work, but thanks a lot for pointing me in that direction, I forgot those things existed, and it's possibly related to them, but the code is very complex, with different handlers/threads/etc ... and I access everything happily without volatiles/transients/syncronization ... I need a refactor I think ;) – rupps Jun 01 '13 at 16:50
  • It sounds like you could use a refactoring pass. Note that transient will not help with anything; that keyword has to do with serialization, not synchronization. It doesn't matter what you synchronize on as long as it's the same thing every time you read and write to that ref. Note also that the synchronize keyword isn't your only choice here. If you use things like AsyncTask or ExecutorService they will provide you with visibility guarantees. – zienkikk Jun 01 '13 at 19:14
  • @Michael & zienikk Wow! I finally found the issue, it was pretty hidden. The problem is that my class exported an inner class as JavaScriptInterface of a WebView. When the class was reinited (in the middle of the process of my answer), it happens that WebView doesn't update the JSIF's until a page reload that didn't happen, so the WeakRef's, etc ... were the ones of an older, retained object inside the heap that pointed whoknowswhere... Later on, from JS, I triggered a call to the inner class, that belonged to the older instance. My god! I had to dig into DDMS to find all this. Thanks guys! – rupps Jun 02 '13 at 18:04
  • to clarify, I have: Activity > MainLogicClass > inner class "JSInterface". WeakRefs, etc are located in MainLogicClass. At some point X i substituted MainLogicClass for a freshone, & from then, managing MainLogicClass from Activity objects was OK, but from WebCore->JSInterface, calls were using the retained heap copy of the older MainLogicClass. That's why there were those strange inconsistencies in method calls depending on the calling thread. I think WebView component or LINT should warn about this, as is pretty deep, but not really difficult to make the mistake. – rupps Jun 02 '13 at 18:15