5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

realm-java で Fatal signal 11 (SIGSEGV) に悩まされた話

Posted at

はじめに

趣味で作っているアプリでrealm-javaを使っているのですが、タイトルの通りFatal signal 11で落ちることがあったのでメモ。
なお、根本的な解決策および原因は分かってません。もうちょっと条件がはっきり分かったらissueに書こうかとも思うのですが、Debugでステップ実行してると発生しなかったりで発生箇所すらはっきりしないのです。。。
ちなみに、本現象は執筆時点で最新の0.79.1でも発生しています。

発生した現象と状況

Realmを今回実装したServiceのプライベートなフィールドとして定義、onCreateで初期化してサービス内で引き回して、最終的にonDestroyで破棄する作りとしていた。

Realm mRealm;

@Override
public void onCreate() {
    mReam = Realm.getInstance(this);
}

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

また、コード中ではRealmResultもプライベートなフィールドとして各所に引き回していました。

RealmResult<Hoge> mRealmResult;

private void getHogeList(String hoge) {
	return mRealmResult.where().equalTo("hoge", hoge).findAll();
}

private void getHogeHogeList(String hogehoge) {
	return mRealmResult.where().equalTo("hogehoge", hogehoge).findAll();
}

なぜこのような作りにしていたかと言うと、ユーザの操作によってカラムhogeで絞り込んだ結果をユーザに提示。
そこから更にユーザ操作でカラムhogehogeに対して絞り込み条件を追加という処理を行っていたから。
realmではRealmResultに対してもクエリーを投げられるので、結果に対してさらに絞り込みという処理がしやすかったんです。
加えてそのサービスが起動中はずっと必要なので、いちいちgetInstance(context)するのが面倒だったのも理由です。。。

ただ、上記のようにしていたコードはNexus6 (Android 5.0.1)では問題なく動くものの、Nexus5 (Android 4.4.4)ではアプリが強制終了してLogcatには以下のようなログだけが出力。。。

Fatal signal 11 (SIGSEGV) at 0xd63794b7 (code=1), thread 6794 (ng.hogehoge)
***以下メモリダンプ***

とりあえず回避策

根本的な解決になっていないかもしれないですが、ReamインスタンスやRealmResultインスタンスの引き回しをやめました。
Realmが必要となるところでRealm.getInstance(context)して、不要となったところでclose()する、これだけです。
これで、クラッシュが発生していたNexus5 (Android 4.4.4)でもクラッシュは発生しなくなりました。

ただ、Realmでクエリーを投げた結果として得られるオブジェクトはいついかなる場合も、coreライブラリを通したメモリへの参照です。
Realmインスタンスがクローズされるともうアクセスすることはできません。

したがって、引き回しが必要なデータは別途Realmのモデルとは別のオブジェクトとして保持していく必要があります。

この辺りはデータの保持方法やロジック自体の再検討が必要になってきます。
自分の場合は、検索条件だけ保持しておいて、必要なときにまとめてクエリーを投げることにしました。

String mHoge;
String mHogeHoge

private HogeListener mHogeListener = new HogeListener() {
	@Override
	public void onUserHogeInput(String searchHoge) {
		mHoge = searchHoge;
		Realm realm = Realm.getInstance(this);
		RealmResult<Hoge> result = getSearchedList(realm);
		// データを保持する
		ArrayList<String> hoogeNames = new ArrayList<>();
		for (Hoge hoge : result) {
			hogeNames.add(hoge.getName());
		}
		// もうRealmは不要なのでクローズ。メソッド内でRealmを完結させる。
		realm.close;
		// 保持したデータでいろいろ処理する
		showHogeSearchResult(hogeNames);		
	}
};

private HogeHogeListener mHogeHogeListener = new HogeHogeListener() {
	@Override
	public void onUserHogeHogeInput(String searchHogeHoge) {
		mHogeHoge = searchHogeHoge;
		Realm realm = Realm.getInstance(this);
		RealmResult<Hoge> result = getSearchedList(realm);
		// 省略
		realm.close;
	}
};

private RealmResult<Hoge> getSearchedList(Realm realm) {
	RealmQuery<Hoge> query = realm.where(Hoge.class);
	if (mHoge != null && mHoge.equals("")) {
		query.equalTo("hoge", mHoge);
	}
	if (mHogeHoge != null && mHogeHoge.equals("")) {
		query.equalTo("hogehoge", mHogeHoge);
	}
	return query.findAll();
}

雑感

このような処理が必要となるケースは多くないとは思いますが、なんだかRealmの良さがスポイルされてしまっている気がします。
だれか、もっと良い解決方法があれば教えて下さい。。。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?