首页 > 解决方案 > E/REALM_JNI: jni: ThrowingException 5, mmap() failed: Out of memory size: 369098752

问题描述

我正在尝试将大型 json 文件下载到 Realm 数据库中。loadCarbay()做得很好,但checkTyres()抛出内存异常Realm.getDefaultInstance()

我在关闭实例时检查了所有领域代码 - 一切都很好。我检查getLocalInstanceCount()过 - 它在崩溃前返回 0。我无法理解我做错了什么?

void checkLoadData(){
        final boolean hasCarbay = hasCarbay();
        final boolean hasTyres = hasTyres();

        if(!hasPersons()||!hasModels()||!hasDeparts()||!hasCarbay||!hasTyres){
            if(checkWifi(this)){
                if(!progressDialog.isShowing())progressDialog.show();
                Thread t = new Thread(new Runnable() {
                    public void run() {
                        final String holding = ses.getString("holding_url");
                        final String curr = ses.getString("curBaseAAURL");
                        loadBase(holding,curr,"");
                        if(!hasPersons()) {
                            h.sendEmptyMessage(STATUS_LOADING_PERSONS_START);
                            loadTablePersons(LoginPageActivity.this, h, STATUS_LOADING_PERSONS_PROGRESS, STATUS_LOADING_PERSONS_END);
                            loadTopicsFromJson(LoginPageActivity.this);
                        }
                        if(!hasModels()){
                            h.sendEmptyMessage(STATUS_LOADING_MODELS_START);
                            loadAlfaModels(LoginPageActivity.this,h,STATUS_LOADING_ALFA_PROGRESS,STATUS_LOADING_ALFA_END);
                        }
                        if(!hasDeparts()){
                            h.sendEmptyMessage(STATUS_LOADING_WS_LINKS_START);
                            loadDepartments(LoginPageActivity.this);
                            h.sendEmptyMessage(STATUS_LOADING_WS_LINKS_END);
                        }
                        if(!hasCarbay){
                            h.sendEmptyMessage(STATUS_LOADING_CARBAY_START);
                            loadCarbayData(LoginPageActivity.this,h,STATUS_LOADING_CARBAY_END);
                            h.sendEmptyMessage(STATUS_LOADING_CARBAY_END);
                        }
                        if(!hasTyres){
                            h.sendEmptyMessage(STATUS_LOADING_TYRE_START);
                            loadTyres(LoginPageActivity.this,h,STATUS_LOADING_TYRE_END);

                        }
                        h.sendEmptyMessage(STATUS_LOADING_TYRE_END);

                    }
                }
                );
                t.start();
            }
            }

    }

    private boolean hasCarbay(){

        Realm realm = Realm.getDefaultInstance();
        long count = realm.where(CarbayBrand.class)
                .count();
        boolean f = count>0;
        realm.close();

        return f;
    }

    private boolean hasTyres(){
        boolean flag = false;
        Realm realm = Realm.getDefaultInstance();

        try{
            long count = realm.where(Tyre.class).count();
            if(count>0){
                Tyre t = realm.where(Tyre.class).findFirst();
                if(t!=null){
                    if(t.getUid()!=null && !t.getUid().isEmpty()){
                        flag = true;
                    }
                }

            }
            Log.d("hasTyre","count="+count);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            realm.close();
        }



        return flag;
    }

//loading data to realm

    synchronized void loadCarbayData(Context context, Handler h, int LOADING_END){
        GlobalParams globalParams = new GlobalParams(context);

        final String url1 = "http://" + globalParams.storage_url + "/carbay/car_bay_data.txt";
        final String url2 =  "http://" + globalParams.storage_url + "/carbay/carbay_ref1.json";
        final String url3 =  "http://" + globalParams.storage_url + "/carbay/carbay_ref2.json";
        final String url4 =  "http://" + globalParams.storage_url + "/carbay/carbay_ref3.json";

        //Log.d("JsonGet", "Realm closed! Realm instances="+Realm.getLocalInstanceCount(Realm.getDefaultConfiguration()));

        Realm realm = Realm.getDefaultInstance();

        try{
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    realm.delete(TradeInCarbay.class);
                }
            });
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    realm.delete(CarbayBrand.class);
                }
            });
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    realm.delete(CarbayModels.class);
                }
            });
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    realm.delete(CarbayModifications.class);
                }
            });
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    realm.delete(CarbayDataLink.class);
                }
            });
            // Insert multiple items using an InputStream
            Log.d("JsonGet", "Старт загрузки справочника Карбей");
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    try {
                        URL url = new URL(url1);
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.connect();
                        InputStream stream = connection.getInputStream();
                        realm.createAllFromJson(TradeInCarbay.class, stream);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });

            Log.d("JsonGet", "Старт загрузки регистра Карбей ч1");

            // Insert multiple items using an InputStream

            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    try {
                        URL url = new URL(url2);
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.connect();
                        InputStream stream = connection.getInputStream();
                        realm.createAllFromJson(CarbayBrand.class, stream);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });


            Log.d("JsonGet", "Старт загрузки регистра Карбей ч2");

            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    try {
                        URL url = new URL(url3);
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.connect();
                        InputStream stream = connection.getInputStream();
                        realm.createAllFromJson(CarbayBrand.class, stream);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });


            Log.d("JsonGet", "Старт загрузки регистра Карбей ч3");

            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    try {
                        URL url = new URL(url4);
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.connect();
                        InputStream stream = connection.getInputStream();
                        realm.createAllFromJson(CarbayBrand.class, stream);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            realm.close();
            //Log.d("JsonGet", "Realm closed! Realm instances="+Realm.getLocalInstanceCount(Realm.getDefaultConfiguration()));
        }



        Message msg;
        msg = h.obtainMessage(LOADING_END, 0, 0);
        h.sendMessage(msg);
    }

    synchronized void loadTyres(Context context, Handler h, int LOADING_END){
        GlobalParams globalParams = new GlobalParams(context);

        final String url1 = "http://" + globalParams.storage_url + "/get_tyres_v2.php";

        Log.d("JsonGet", "Старт загрузки справочника шин");

        try(Realm realm = Realm.getDefaultInstance()) {
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    realm.delete(Tyre.class);
                }
            });

            // Insert multiple items using an InputStream
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    try {
                        URL url = new URL(url1);
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.connect();
                        InputStream stream = connection.getInputStream();
                        realm.createAllFromJson(Tyre.class, stream);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }catch (Exception e){
            e.printStackTrace();
        }

        Message msg;
        msg = h.obtainMessage(LOADING_END, 0, 0);
        h.sendMessage(msg);
    }

我的 logcat 错误消息

2019-07-12 15:05:09.347 11321-11362/com.lx2.crm E/REALM_JNI: jni: ThrowingException 5, mmap() failed: Out of memory size: 369098752 offset: 0 in /Users/Nabil/Dev/realm/master/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 101, .
2019-07-12 15:05:09.350 11321-11362/com.lx2.crm E/REALM_JNI: Exception has been thrown: Unrecoverable error. mmap() failed: Out of memory size: 369098752 offset: 0 in /Users/Nabil/Dev/realm/master/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 101
2019-07-12 15:05:09.352 11321-11362/com.lx2.crm E/AndroidRuntime: FATAL EXCEPTION: Thread-10
    Process: com.lx2.crm, PID: 11321
    io.realm.exceptions.RealmError: Unrecoverable error. mmap() failed: Out of memory size: 369098752 offset: 0 in /Users/Nabil/Dev/realm/master/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 101
        at io.realm.internal.OsSharedRealm.nativeGetSharedRealm(Native Method)
        at io.realm.internal.OsSharedRealm.<init>(OsSharedRealm.java:184)
        at io.realm.internal.OsSharedRealm.getInstance(OsSharedRealm.java:254)
        at io.realm.internal.OsSharedRealm.getInstance(OsSharedRealm.java:244)
        at io.realm.RealmCache.doCreateRealmOrGetFromCache(RealmCache.java:319)
        at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:282)
        at io.realm.Realm.getDefaultInstance(Realm.java:332)
        at com.lx2.crm.LoginPageActivity.loadTyres(LoginPageActivity.java:1154)
        at com.lx2.crm.LoginPageActivity$11.run(LoginPageActivity.java:1001)
        at java.lang.Thread.run(Thread.java:764)

标签: javaandroidrealmout-of-memory

解决方案


它看起来像领域没有释放内存,直到异步任务没有完成。这就是为什么即使我尝试分割正在加载的文件时也会出现内存不足错误的原因。我的解决方案是划分加载文件并为每个文件制作异步任务。每个异步任务都由前一个任务中的回调开始。有点难看,但它的工作原理


推荐阅读