E/REALM_JNI:jni:ThrowingException 5,mmap() 失败:内存不足:369098752
E/REALM_JNI: jni: ThrowingException 5, mmap() failed: Out of memory size: 369098752
我正在尝试将大型 json 文件下载到 Realm 数据库中。 loadCarbay()
表现不错,但是 checkTyres()
在 Realm.getDefaultInstance()
上抛出内存异常
我已经在关闭实例时检查了所有领域代码 - 一切正常。我在崩溃前检查了 getLocalInstanceCount()
- returns 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.run(LoginPageActivity.java:1001)
at java.lang.Thread.run(Thread.java:764)
Ilshat,欢迎来到 Whosebug。
loadTyres() 的一个区别是它使用了 try-with-resources 语句:
try(Realm realm = Realm.getDefaultInstance()) {
虽然 loadCarbay() 不是:
Realm realm = Realm.getDefaultInstance();
try{
也许 Realm 与 try-with-resource 声明不兼容。
尝试让 loadCarbay() 在 try
块之前获取领域实例,看看是否可以解决问题。这只是一个猜测。
如果你这样做,记得还要添加一个带有 realm.close();
的 finally 块
我发现为什么每次我获取实例时 Realm 都会崩溃——我的设备内存不足。我在另一台内存大的设备上安装我的应用程序,一切正常。
似乎在异步任务未完成之前领域不会释放内存。这就是为什么即使我尝试分割正在加载的文件时也会出现内存不足错误的原因。我的解决方案是划分加载文件并为每个文件创建异步任务。每个异步任务都由前一个任务的回调开始。有点难看,但它有效
我正在尝试将大型 json 文件下载到 Realm 数据库中。 loadCarbay()
表现不错,但是 checkTyres()
在 Realm.getDefaultInstance()
我已经在关闭实例时检查了所有领域代码 - 一切正常。我在崩溃前检查了 getLocalInstanceCount()
- returns 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.run(LoginPageActivity.java:1001)
at java.lang.Thread.run(Thread.java:764)
Ilshat,欢迎来到 Whosebug。
loadTyres() 的一个区别是它使用了 try-with-resources 语句:
try(Realm realm = Realm.getDefaultInstance()) {
虽然 loadCarbay() 不是:
Realm realm = Realm.getDefaultInstance();
try{
也许 Realm 与 try-with-resource 声明不兼容。
尝试让 loadCarbay() 在 try
块之前获取领域实例,看看是否可以解决问题。这只是一个猜测。
如果你这样做,记得还要添加一个带有 realm.close();
我发现为什么每次我获取实例时 Realm 都会崩溃——我的设备内存不足。我在另一台内存大的设备上安装我的应用程序,一切正常。
似乎在异步任务未完成之前领域不会释放内存。这就是为什么即使我尝试分割正在加载的文件时也会出现内存不足错误的原因。我的解决方案是划分加载文件并为每个文件创建异步任务。每个异步任务都由前一个任务的回调开始。有点难看,但它有效