Realm android应用程序崩溃:io.realm.exceptions.RealmError:不可恢复的错误。 mmap()失败:内存不足

时间:2016-06-27 10:31:48

标签: java android database realm

我正在为我的下一个项目评估Realm数据库(Android)。我决定编写一个测试应用程序来插入100万个对象并检查Realm数据库的性能。测试应用程序是一个简单的Android应用程序。 用户可以指定要创建的特定模型类的随机对象的数量,并在后台的IntentService中创建对象。在创建对象时,活动将显示领域中的对象总数。

IntentService,用于创建随机对象。

package example.com.realmcrashapplication;

import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import io.realm.Realm;

public class BackendService extends IntentService {

public static final String TASK_DETAILS = "taskDetails";
public static final String INSERTION_COUNT = "insertionCount";    
private static final int insertsPerTransaction = 1000;
private int remainingInsertions = 0;

public BackendService() {
    super(BackendService.class.getName());
}

@Override
protected void onHandleIntent(Intent intent) {
    Bundle args = intent.getBundleExtra(TASK_DETAILS);
    if(args != null) {
        if(args.containsKey(INSERTION_COUNT)){
            final int count = args.getInt(INSERTION_COUNT);
            if(count>0){
                remainingInsertions = count;
                while(remainingInsertions>0){
                    final int c;
                    if(remainingInsertions>insertsPerTransaction){
                        c=insertsPerTransaction;
                    }else{
                        c=remainingInsertions;
                    }
                    Realm realm = Realm.getDefaultInstance();
                    final Person p = Person.getRandomPerson();
                    realm.executeTransaction(new Realm.Transaction() {
                        @Override
                        public void execute(Realm realm) {
                            for(int i=0;i<c;++i) {
                                realm.copyToRealm(p);
                            }
                        }
                    });
                    realm.close();
                    remainingInsertions-=c;
                }
            }

        }
    }
 }

}

每当我尝试创建超过100k的对象(我的目标是创建100万个对象)时,应用程序崩溃时会出现以下错误。注意:内存消耗(从Android监视器看到)在8.0MB到11MB之间变化插入。

example.com.realmcrashapplication D/REALM:   jni: ThrowingException 11, mmap() failed: Out of memory size: 671088640 offset:   0 in io_realm_internal_SharedGroup.cpp line 188, .
example.com.realmcrashapplication D/REALM:   Exception has been throw: Unrecoverable error. mmap() failed: Out of memory size: 671088640 offset: 0 in io_realm_internal_SharedGroup.cpp line 188
example.com.realmcrashapplication W/dalvikvm: threadid=13: thread exiting with uncaught exception (group=0x41bc2c08)
example.com.realmcrashapplication  E/AndroidRuntime: FATAL EXCEPTION:   IntentService[example.com.realmcrashapplication.BackendService]
                                                                                        Process: example.com.realmcrashapplication, PID: 27140
                                                                                         io.realm.exceptions.RealmError: Unrecoverable error. mmap() failed: Out of memory size: 671088640 offset: 0 in io_realm_internal_SharedGroup.cpp line 188
                                                                                          at io.realm.internal.SharedGroup.nativeCommitAndContinueAsRead(Native Method)
                                                                                         at io.realm.internal.SharedGroup.commitAndContinueAsRead(SharedGroup.java:149)
                                                                                         at io.realm.internal.ImplicitTransaction.commitAndContinueAsRead(ImplicitTransaction.java:62)
                                                                                         at io.realm.internal.SharedGroupManager.commitAndContinueAsRead(SharedGroupManager.java:118)
                                                                                         at io.realm.BaseRealm.commitTransaction(BaseRealm.java:362)
                                                                                         at io.realm.BaseRealm.commitTransaction(BaseRealm.java:349)
                                                                                         at io.realm.Realm.commitTransaction(Realm.java:121)
                                                                                         at io.realm.Realm.executeTransaction(Realm.java:967)
                                                                                         at example.com.realmcrashapplication.BackendService.onHandleIntent(BackendService.java:42)
                                                                                         at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
                                                                                         at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                         at android.os.Looper.loop(Looper.java:146)
                                                                                         at android.os.HandlerThread.run(HandlerThread.java:61)

我已经尝试将每个事务的插入次数从1000减少到10,但结果是一样的。我的手机中有足够的空间。所以它不是关于存储我猜。 100K插入后的文件大小超过600MB(在145K对象后为704MB)

Realm Library 1.0.1 Android Java

测试:三星Galaxy Note 2 Android 4.4.2 API 19。

模型类

package example.com.realmcrashapplication;

import java.util.Date;
import io.realm.RealmList;
import io.realm.RealmObject;

public class Person extends RealmObject{
private int field1;
private String field2;
private Date field3;
private String field4;
private Date field5;
private String field6;
private String field7;
private int field8;
private double field9;
private String field10;
private int field11;
private int field12;
private double field13;
private double field14;
private int field15;
private String field16;
private double field17;
private boolean field18;
private String field19;
private double field20;
private boolean field21;
private boolean field22;
private int field23;
private ExtraInfo1 field24;
private ExtraInfo1 field25;
private ExtraInfo1 field26;
private ExtraInfo1 field27;
private ExtraInfo1 field28;
private RealmList<ExtraInfo2> field29;
private Integer field30;
private String field31;
private String field32;
private String field33;
private String field34;
private String field35;
private String field36;
private Address field37;
private boolean field38;
private Date field39;
private int field40;
private int field41;
private double field42;
private double field43;
private String field44;
private String field45;
private String field46;
private Address field47;
private int field48;
private String field49;
private Date field50;
private String field51;
private boolean field52;
private RealmList<ExtraInfo3> field53;
private double field54;
private double field55;
private double field56;
private RealmList<Person> family;

public void setField1(int field1) {
    this.field1 = field1;
}
public void setField2(String field2) {
    this.field2 = field2;
}
public void setField3(Date field3) {
    this.field3 = field3;
}
public void setField4(String field4) {
    this.field4 = field4;
}
public void setField5(Date field5) {
    this.field5 = field5;
}
public void setField6(String field6) {
    this.field6 = field6;
}
public void setField7(String field7) {
    this.field7 = field7;
}
public void setField8(int field8) {
    this.field8 = field8;
}
public void setField9(double field9) {
    this.field9 = field9;
}
public void setField10(String field10) {
    this.field10 = field10;
}
public void setField11(int field11) {
    this.field11 = field11;
}
public void setField12(int field12) {
    this.field12 = field12;
}
public void setField13(double field13) {
    this.field13 = field13;
}
public void setField14(double field14) {
    this.field14 = field14;
}
public void setField15(int field15) {
    this.field15 = field15;
}
public void setField16(String field16) {
    this.field16 = field16;
}
public void setField17(double field17) {
    this.field17 = field17;
}
public void setField18(boolean field18) {
    this.field18 = field18;
}
public void setField19(String field19) {
    this.field19 = field19;
}
public void setField20(double field20) {
    this.field20 = field20;
}
public void setField21(boolean field21) {
    this.field21 = field21;
}
public void setField22(boolean field22) {
    this.field22 = field22;
}
public void setField23(int field23) {
    this.field23 = field23;
}
public void setField24(ExtraInfo1 field24) {
    this.field24 = field24;
}
public void setField25(ExtraInfo1 field25) {
    this.field25 = field25;
}
public void setField26(ExtraInfo1 field26) {
    this.field26 = field26;
}
public void setField27(ExtraInfo1 field27) {
    this.field27 = field27;
}
public void setField28(ExtraInfo1 field28) {
    this.field28 = field28;
}
public void setField29(RealmList<ExtraInfo2> field29) {
    this.field29 = field29;
}
public void setField30(Integer field30) {
    this.field30 = field30;
}
public void setField31(String field31) {
    this.field31 = field31;
}
public void setField32(String field32) {
    this.field32 = field32;
}
public void setField33(String field33) {
    this.field33 = field33;
}
public void setField34(String field34) {
    this.field34 = field34;
}
public void setField35(String field35) {
    this.field35 = field35;
}
public void setField36(String field36) {
    this.field36 = field36;
}
public void setField37(Address field37) {
    this.field37 = field37;
}
public void setField38(boolean field38) {
    this.field38 = field38;
}
public void setField39(Date field39) {
    this.field39 = field39;
}
public void setField40(int field40) {
    this.field40 = field40;
}
public void setField41(int field41) {
    this.field41 = field41;
}
public void setField42(double field42) {
    this.field42 = field42;
}
public void setField43(double field43) {
    this.field43 = field43;
}
public void setField44(String field44) {
    this.field44 = field44;
}
public void setField45(String field45) {
    this.field45 = field45;
}
public void setField46(String field46) {
    this.field46 = field46;
}
public void setField47(Address field47) {
    this.field47 = field47;
}
public void setField48(int field48) {
    this.field48 = field48;
}
public void setField49(String field49) {
    this.field49 = field49;
}
public void setField50(Date field50) {
    this.field50 = field50;
}
public void setField51(String field51) {
    this.field51 = field51;
}
public void setField52(boolean field52) {
    this.field52 = field52;
}
public void setField53(RealmList<ExtraInfo3> field53) {
    this.field53 = field53;
}
public void setField54(double field54) {
    this.field54 = field54;
}
public void setField55(double field55) {
    this.field55 = field55;
}
public void setField56(double field56) {
    this.field56 = field56;
}
public void setFamily(RealmList<Person> family) {
    this.family = family;
}
public static Person getRandomPerson(){
    Person p = new Person();
    p.setField1(9);
    p.setField2(HelperClass.getRandomString(15));
    p.setField3(HelperClass.getRandomDate());
    p.setField4(HelperClass.getRandomString(15));
    p.setField5(HelperClass.getRandomDate());
    p.setField6(HelperClass.getRandomString(24));
    p.setField7(HelperClass.getRandomString(100));
    p.setField8(9);
    p.setField9(0.567);
    p.setField10(HelperClass.getRandomString(3));
    p.setField11(9);
    p.setField12(1);
    p.setField13(45.00);
    p.setField14(0);
    p.setField15(1);
    p.setField16(HelperClass.getRandomString(15));
    p.setField17(5);
    p.setField18(true);
    p.setField19(HelperClass.getRandomString(15));
    p.setField20(5);
    p.setField21(true);
    p.setField22(true);
    p.setField23(5);
    p.setField24(ExtraInfo1.getRandomExtraInfo1());
    p.setField25(ExtraInfo1.getRandomExtraInfo1());
    p.setField26(ExtraInfo1.getRandomExtraInfo1());
    p.setField27(ExtraInfo1.getRandomExtraInfo1());
    p.setField28(ExtraInfo1.getRandomExtraInfo1());

    RealmList<ExtraInfo2> extraInfo2Items = new RealmList<>();
    for (int i = 0; i < 10; ++i) {
        ExtraInfo2 extraInfo2 = ExtraInfo2.getRandomExtraInfo2();
        extraInfo2Items.add(extraInfo2);
    }
    p.setField29(extraInfo2Items);
    p.setField30(1);
    p.setField31(HelperClass.getRandomString(24));
    p.setField32(HelperClass.getRandomString(24));
    p.setField33(HelperClass.getRandomString(10));
    p.setField34(HelperClass.getRandomString(10));
    p.setField35(HelperClass.getRandomString(128));
    p.setField36(HelperClass.getRandomString(10));
    p.setField37(Address.getRandomAddress());
    p.setField38(true);
    p.setField39(HelperClass.getRandomDate());
    p.setField40(1);
    p.setField41(1);
    p.setField42(10);
    p.setField43(0.00);
    p.setField44(HelperClass.getRandomString(24));
    p.setField45(HelperClass.getRandomString(100));
    p.setField46(HelperClass.getRandomString(30));
    p.setField47(Address.getRandomAddress());
    p.setField48(30);
    p.setField49(HelperClass.getRandomString(30));
    p.setField50(HelperClass.getRandomDate());
    p.setField51(HelperClass.getRandomString(100));
    p.setField52(true);

    RealmList<ExtraInfo3> extraInfo3List = new RealmList<>();
    for (int i = 0; i < 5; ++i) {
        ExtraInfo3 extraInfo3 = ExtraInfo3.getRandomExtraInfo3();
        extraInfo3List.add(extraInfo3);
    }
    p.setField53(extraInfo3List);
    p.setField54(100);
    p.setField55(100);
    p.setField56(0);
    return p;
}
}

地址

package example.com.realmcrashapplication;

import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;
import io.realm.RealmObject;

public class Address extends RealmObject{
private String line1;
private String line2;
private String zip;
private String city;
private String state;
private String country;
private int type;

public String getLine1() {
    return line1;
}

public void setLine1(String line1) {
    this.line1 = line1;
}

public String getLine2() {
    return line2;
}

public void setLine2(String line2) {
    this.line2 = line2;
}

public String getZip() {
    return zip;
}

public void setZip(String zip) {
    this.zip = zip;
}

public String getCity() {
    return city;
}

public void setCity(String city) {
    this.city = city;
}

public String getState() {
    return state;
}

public void setState(String state) {
    this.state = state;
}

public String getCountry() {
    return country;
}

public void setCountry(String country) {
    this.country = country;
}

public int getType() {
    return type;
}

public void setType(int type) {
    this.type = type;
}

public static Address getRandomAddress(){
    Address a = new Address();
    a.setLine1(HelperClass.getRandomString(49));
    a.setLine2(HelperClass.getRandomString(49));
    a.setZip(HelperClass.getRandomString(10));
    a.setCity(HelperClass.getRandomString(24));
    a.setState(HelperClass.getRandomString(20));
    a.setCountry(HelperClass.getRandomString(30));
    a.setType(1);
    return a;
}
}

ExtraInfo1

package example.com.realmcrashapplication;

import io.realm.RealmObject;

public class ExtraInfo1 extends RealmObject {
private String field1;
private boolean field2;
private int field3;
private int field4;
private double field5;
private double field6;
private int field7;
private boolean field8;
private String field9;
private double field10;
private String field11;
private double field12;
private boolean field13;

public void setField1(String field1) {
    this.field1 = field1;
}
public void setField2(boolean field2) {
    this.field2 = field2;
}
public void setField3(int field3) {
    this.field3 = field3;
}
public void setField4(int field4) {
    this.field4 = field4;
}
public void setField5(double field5) {
    this.field5 = field5;
}
public void setField6(double field6) {
    this.field6 = field6;
}
public void setField7(int field7) {
    this.field7 = field7;
}
public void setField8(boolean field8) {
    this.field8 = field8;
}
public void setField9(String field9) {
    this.field9 = field9;
}
public void setField10(double field10) {
    this.field10 = field10;
}
public void setField11(String field11) {
    this.field11 = field11;
}
public void setField12(double field12) {
    this.field12 = field12;
}
public void setField13(boolean field13) {
    this.field13 = field13;
}

public static ExtraInfo1 getRandomExtraInfo1(){
    ExtraInfo1 info = new ExtraInfo1();
    info.setField1(HelperClass.getRandomString(10));
    info.setField2(true);
    info.setField3(1);
    info.setField4(1);
    info.setField5(0);
    info.setField6(0);
    info.setField7(1);
    info.setField8(true);
    info.setField9(HelperClass.getRandomString(15));
    info.setField10(5);
    info.setField11(HelperClass.getRandomString(15));
    info.setField12(5);
    info.setField13(true);
    return info;
}
}

ExtraInfo2

package example.com.realmcrashapplication;

import io.realm.RealmObject;

public class ExtraInfo2 extends RealmObject {
private int field1;
private String field2;
private double field3;
private boolean field4;
private double field5;
private String field6;
private double field7;
private int field8;
private double field9;
private double field10;
private String field11;
private boolean field12;
private String field13;
private double field14;
private String field15;
private double field16;
private boolean field17;

public void setField1(int field1) {
    this.field1 = field1;
}
public void setField2(String field2) {
    this.field2 = field2;
}

public void setField3(double field3) {
    this.field3 = field3;
}
public void setField4(boolean field4) {
    this.field4 = field4;
}
public void setField5(double field5) {
    this.field5 = field5;
}
public void setField6(String field6) {
    this.field6 = field6;
}
public void setField7(double field7) {
    this.field7 = field7;
}
public void setField8(int field8) {
    this.field8 = field8;
}
public void setField9(double field9) {
    this.field9 = field9;
}

public void setField10(double field10) {
    this.field10 = field10;
}
public void setField11(String field11) {
    this.field11 = field11;
}
public void setField12(boolean field12) {
    this.field12 = field12;
}
public void setField13(String field13) {
    this.field13 = field13;
}
public void setField14(double field14) {
    this.field14 = field14;
}
public void setField15(String field15) {
    this.field15 = field15;
}
public void setField16(double field16) {
    this.field16 = field16;
}
public void setField17(boolean field17) {
    this.field17 = field17;
}

public static ExtraInfo2 getRandomExtraInfo2(){
    ExtraInfo2 extraInfo2 = new ExtraInfo2();
    extraInfo2.setField1(1);
    extraInfo2.setField2(HelperClass.getRandomString(15));
    extraInfo2.setField3(18.0);
    extraInfo2.setField4(true);
    extraInfo2.setField5(9.0);
    extraInfo2.setField6("value");
    extraInfo2.setField7(1.0);
    extraInfo2.setField8(1);
    extraInfo2.setField9(0.0);
    extraInfo2.setField10(0.0);
    extraInfo2.setField11(HelperClass.getRandomString(100));
    extraInfo2.setField12(true);
    extraInfo2.setField13(HelperClass.getRandomString(15));
    extraInfo2.setField14(5);
    extraInfo2.setField15(HelperClass.getRandomString(15));
    extraInfo2.setField16(5);
    extraInfo2.setField17(true);
    return extraInfo2;
}
}

ExtraInfo3

package example.com.realmcrashapplication;

import java.util.Date;
import io.realm.RealmObject;

public class ExtraInfo3 extends RealmObject {
private Date field1;
private int field2;
private String field3;
private double field4;
private String field5;
private String field6;

public void setField1(Date field1) {
    this.field1 = field1;
}
public void setField2(int field2) {
    this.field2 = field2;
}
public void setField3(String field3) {
    this.field3 = field3;
}
public void setField4(double field4) {
    this.field4 = field4;
}
public void setField5(String field5) {
    this.field5 = field5;
}
public void setField6(String field6) {
    this.field6 = field6;
}

public static ExtraInfo3 getRandomExtraInfo3(){
    ExtraInfo3 extraInfo3 = new ExtraInfo3();
    extraInfo3.setField1(HelperClass.getRandomDate());
    extraInfo3.setField2(1);
    extraInfo3.setField3(HelperClass.getRandomString(10));
    extraInfo3.setField4(10.00);
    extraInfo3.setField5(HelperClass.getRandomString(10));
    extraInfo3.setField6(HelperClass.getRandomString(24));
    return extraInfo3;
}
}

MainActivity

package example.com.realmcrashapplication;

import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.widget.TextView;
import io.realm.Realm;
import io.realm.RealmChangeListener;
import io.realm.RealmResults;
import io.realm.Sort;

public class MainActivity extends AppCompatActivity {
    private Realm realm;
    private RealmResults<Person> persons;
    private RealmChangeListener personsChangeListener;
    private TextView personCountTextView;
    private Intent backgroundIntent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        personCountTextView = (TextView)findViewById(R.id.personCountText);
        TextView locationText = (TextView)findViewById(R.id.locationText);
        locationText.setText(MyApplication.location);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                InsertPersonsDialogFragment newFragment = new InsertPersonsDialogFragment();
                newFragment.setClickListener(new InsertPersonsDialogFragment.ClickListener() {
                    @Override
                    public void onInsertItems(int count) {
                        insertPersons(count);
                    }
                });
                newFragment.show(getSupportFragmentManager(), "insertPersonsDialog");
            }
        });
        backgroundIntent = new Intent(MainActivity.this,BackendService.class);
    }
    @Override
    public void onStart() {
        super.onStart();
        realm = Realm.getDefaultInstance();
        persons = realm.where(Person.class).findAllSortedAsync("field3", Sort.DESCENDING);
        personsChangeListener = new RealmChangeListener<RealmResults<Person>>() {
            @Override
            public void onChange(final RealmResults<Person> personsList) {
                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if(personCountTextView!=null) {
                            String size = Integer.toString(personsList.size());
                            personCountTextView.setText("Number of persons : "+size);
                        }

                    }
                });
            }
        };
        persons.addChangeListener(personsChangeListener);
    }
    @Override
    public void onStop() {
        super.onStop();
        if(personsChangeListener!=null){
            realm.removeChangeListener(personsChangeListener);
        }
        realm.close();
    }
    private void insertPersons(final int count) {
        Bundle args = new Bundle();
        args.putInt(BackendService.INSERTION_COUNT, count);
        backgroundIntent.putExtra(BackendService.TASK_DETAILS, args);
        startService(backgroundIntent);
    }
}

所有MyApplication

public class MyApplication extends Application {
    public static String location = "";
    @Override
    public void onCreate() {
        super.onCreate();
        File dir = new File("/sdcard/realm2");
        if(!dir.exists()){
            dir.mkdirs();
        }
        location = dir.getAbsolutePath();
        RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(dir).
                                                    deleteRealmIfMigrationNeeded().
                                                    build();
        Realm.setDefaultConfiguration(realmConfiguration);
    }
}

0 个答案:

没有答案