Possible Realm memory leak in Android when creating Observable from Where clause

Question!

Perhaps I don't understand how to use Realm with Observables properly properly but I seem to be getting a Realm memory leak when I create an Observable from a Realm Where and Subscribe to it. I close the Realm in onDestroy() and unsubscribe from the Observable in onPause(). However, if I add and back out of the following Fragment a few times (it is added to the BackStack and removed on back press):

public class RealmFragment extends android.support.v4.app.Fragment {

    private Realm mRealm;
    private Subscription mSubscription;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_realm, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mRealm = Realm.getDefaultInstance();

        mSubscription = mRealm.where(Person.class)
            .findAllAsync()
            .asObservable()
            .subscribe(new Action1<RealmResults<Person>>() {
                @Override
                public void call(RealmResults<Person> persons) {
                    Log.d("RXREALM", "OnNext called");
                }
            });
    }

    @Override
    public void onPause() {
        super.onPause();
        mSubscription.unsubscribe();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mRealm.close();
    }
}

I've noticed if I do a couple GC's then a heap dump in Android studio there is multiple instances of Realm and RealmResult equal to the number of times I started the Fragment. I keep no reference to them anywhere. There is no reference to the RealmFragment after the last time I've left it.

I've noticed if I DO NOT unsubscribe from the Where Subscription the count of Realm objects doesn't increase. The count of RealmResults still increases.

I made an empty project to test this. RxJava and Realm are up-to-date. Any clarification regarding why this happens or how Realm manages Observables is appreciated. The whole empty project can be found here while I investigate the issue: https://github.com/willjgriff/android-realm-leak



Answers

Realms code for generating Observables are here: https://github.com/realm/realm-java/blob/master/realm/realm-library/src/main/java/io/realm/rx/RealmObservableFactory.java

As long as you don't unsubscribe an observable, Realm will keep a strong reference to it, but it should release that reference when you unsubscribe.

But without Without more context about your code, it is hard to tell exactly what is going on. Can you post an entire example.



Window messages can only pass around 2 integers (the wParam and lParam parameters).

Integer values by themselves do not require any special marshaling across module/process boundaries, they can be passed around as-is. They are also very small to pas around, store in message queues, etc.

For WM_COMMAND in particular, lParam may contain an HWND value, so the other message values (notification code and identifier) can only be passed in wParam only. They are small enough to be stuffed into wParam directly, thus making it easy to pass around 3 values where only 2 values are allowed.

The alternative requires allocating memory for a struct that contains the separate integers, and then pass a pointer to that struct around in one of the message parameters. And many window messages do exactly that, but usually only when the sender and receiver are in the same process, otherwise it requires marshaling the struct data across module/process boundaries, which is a lot of overhead for simple messaging.

It also puts the burden on the receiver to free the allocated memory, since WM_COMMAND is a posted message that goes through the receiving window's message queue. The sender does not wait for the message to be processed, and thus would not be able to free the struct memory after posting the message. The allocated memory would have to stay alive in memory until the message is finally processed by the receiving window procedure.

Sent messages, on the other hand, go directly to a window procedure and block the sender until processed, so they do not have to worry this, the sender can free the memory after the message is sent. But making all multi-value messages, especially status messages, do this would be a big bottleneck on the system.

In general, it is easier and less overhead to stuff shorter integers into a larger integer whenever possible, especially in posted messages (though sent messages can certainly do it, too).



If I am reading this correctly, Message would contain a List<MessageUser>.

If that's the case then this should get you close:

var List<Message> messages = 
    ( from m 
      in db.Messages 
      where 
          m.UserID == userid || m.MessageUsers.Any(mu => mu.UserID == userID) 
      select m).ToList();
By : Sam Axe


This video can help you solving your question :)
By: admin