SQLiteException: unknown error (code 0): Native could not create new byte[]

牧云@^-^@ 提交于 2021-01-28 03:02:42

问题


I'm getting this error when trying to query up to 30 objects, each object has field byte[] which weights 100x100 ARGB_8888 bitmap data ~ 39kb

I'm using OrmLite 4.45 version. on a Samsung GT n8000 tablet (max heap size 64mb)

Here's stacktrace:

android.database.sqlite.SQLiteException: unknown error (code 0): Native could not create new byte[]
    at android.database.CursorWindow.nativeGetBlob(Native Method)
    at android.database.CursorWindow.getBlob(CursorWindow.java:403)
    at android.database.AbstractWindowedCursor.getBlob(AbstractWindowedCursor.java:45)
    at com.j256.ormlite.android.AndroidDatabaseResults.getBytes(AndroidDatabaseResults.java:161)
    at com.j256.ormlite.field.types.ByteArrayType.resultToSqlArg(ByteArrayType.java:41)
    at com.j256.ormlite.field.BaseFieldConverter.resultToJava(BaseFieldConverter.java:24)
    at com.j256.ormlite.field.FieldType.resultToJava(FieldType.java:798)
    at com.j256.ormlite.stmt.mapped.BaseMappedQuery.mapRow(BaseMappedQuery.java:60)
    at com.j256.ormlite.stmt.SelectIterator.getCurrent(SelectIterator.java:270)
    at com.j256.ormlite.stmt.SelectIterator.nextThrow(SelectIterator.java:161)
    at com.j256.ormlite.stmt.StatementExecutor.query(StatementExecutor.java:187)
    at com.j256.ormlite.dao.BaseDaoImpl.query(BaseDaoImpl.java:263)
    at com.j256.ormlite.dao.EagerForeignCollection.(EagerForeignCollection.java:37)
    at com.j256.ormlite.field.FieldType.buildForeignCollection(FieldType.java:781)
    at com.j256.ormlite.stmt.mapped.BaseMappedQuery.mapRow(BaseMappedQuery.java:82)
    at com.j256.ormlite.android.AndroidDatabaseConnection.queryForOne(AndroidDatabaseConnection.java:186)
    at com.j256.ormlite.stmt.mapped.MappedQueryForId.execute(MappedQueryForId.java:38)
    at com.j256.ormlite.field.FieldType.assignField(FieldType.java:540)
    at com.j256.ormlite.stmt.mapped.BaseMappedQuery.mapRow(BaseMappedQuery.java:71)
    at com.j256.ormlite.stmt.SelectIterator.getCurrent(SelectIterator.java:270)
    at com.j256.ormlite.stmt.SelectIterator.nextThrow(SelectIterator.java:161)
    at com.j256.ormlite.stmt.StatementExecutor.query(StatementExecutor.java:187)
    at com.j256.ormlite.dao.BaseDaoImpl.query(BaseDaoImpl.java:263)
    at com.j256.ormlite.stmt.QueryBuilder.query(QueryBuilder.java:319)
    at com.j256.ormlite.stmt.Where.query(Where.java:485)
    at com.j256.ormlite.dao.BaseDaoImpl.queryForEq(BaseDaoImpl.java:243)    

here's logcat:

05-16 14:05:24.561: D/dalvikvm(4163): GC_CONCURRENT freed 1247K, 10% free 18046K/19911K, paused 11ms+3ms, total 30ms
05-16 14:05:24.561: D/dalvikvm(4163): WAIT_FOR_CONCURRENT_GC blocked 10ms
05-16 14:05:24.686: D/dalvikvm(4163): GC_CONCURRENT freed 119K, 4% free 19922K/20743K, paused 11ms+2ms, total 28ms
05-16 14:05:24.686: D/dalvikvm(4163): WAIT_FOR_CONCURRENT_GC blocked 15ms
... whole ton of these
05-16 14:05:27.261: D/dalvikvm(4163): GC_CONCURRENT freed 109K, 2% free 62754K/63495K, paused 12ms+5ms, total 36ms
05-16 14:05:27.261: D/dalvikvm(4163): WAIT_FOR_CONCURRENT_GC blocked 20ms
05-16 14:05:27.366: I/dalvikvm-heap(4163): Clamp target GC heap from 65.738MB to 64.000MB
  • Is such fast growth of memory usage normal?
  • What do you think about splitting query into chunks and explicitly calling System.gc() between those separate queries?

Thanks!


回答1:


Is such fast growth of memory usage normal?

No it isn't.

What do you think about splitting query into chunks and explicitly calling System.gc() between those separate queries?

No, this most likely would not fix the issue. You need to resolve the underlying memory issue directly.

After looking at your code and entities that you did not provide in your post, this is not a ORMLite issue but a entity problem.

You have a Gallery of Photos. Each photo has a possibly large array of byte image data -- maybe 50+k. The problem is that the Gallery has an eager foreign collection of Photos:

@ForeignCollectionField(eager = true)
private ForeignCollection<Photo> photos;

And then each Photo has an auto-refreshed version of its parent Gallery.

@DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = GALLERY)
private Gallery gallery;

This sets up an eager fetch loop which causes ORMLite to do something like the following:

  1. Whenever ORMLite tries to load the Gallery into memory...
  2. it is being asked to do another query and load all of the photos associated with the Gallery into memory because of the eager collection.
  3. For each of those Photo instances, it is being asked to do another query to get the associated Gallery into memory because of the auto-refreshed parent.
  4. And for that Gallery it is asked to load all of the Photos into memory.
  5. ... ORMLite actually has an escape but still does this 3 levels down.

ORMLite has no magic view of the Gallery and Photo instances so it attach the parent Gallery to the foreign field in the Photos. If you want this then I'd see the ObjectCache solution below.

There are a number of ways you can fix this:

  • I'd recommend not using foreignAutoRefresh = true. If you need the Gallery of a photo then you can get it by doing galleryDao.refresh(photo.getGallery()). This breaks the chain of eager fetches.
  • You could also make the photos collection not be eager. A lazy loaded collection would go more times to the database but would also break the cycle.
  • If you really must have all of the eager collection and refreshing then the best solution however would be the introduction of an ObjectCache. You may have to clear the cache often but each of the DAOs would then look in the cache and return the same object entity even with the eager fetch loop going on.

    galleryDao = getHelper().getRuntimeExceptionDao(Gallery.class);
    galleryDao.setObjectCache(true);
    photoDao = getHelper().getRuntimeExceptionDao(Photo.class);
    photoDao.setObjectCache(true);
    ...
    // if you load a lot of objects into memory, you must clear the cache often
    galleryDao.clearObjectCache();
    photoDao.clearObjectCache();
    


来源:https://stackoverflow.com/questions/16585221/sqliteexception-unknown-error-code-0-native-could-not-create-new-byte

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!