SQLiteException:未知错误(代码 0):本机无法创建新字节 [] [英] SQLiteException: unknown error (code 0): Native could not create new byte[]
问题描述
我在尝试查询多达 30 个对象时遇到此错误,每个对象都有 字段字节[],其权重为 100x100 ARGB_8888 位图数据~39kb
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
我使用的是 OrmLite 4.45 版本.在三星 GT n8000 平板电脑上(最大堆大小 64mb)
I'm using OrmLite 4.45 version. on a Samsung GT n8000 tablet (max heap size 64mb)
这是堆栈跟踪:
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)
这里是 logcat:
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
- 内存使用量增长如此之快正常吗?
- 您如何看待将查询拆分为多个块并在这些单独的查询之间显式调用 System.gc()?
谢谢!
推荐答案
内存使用量增长这么快正常吗?
Is such fast growth of memory usage normal?
不,不是.
您如何看待将查询拆分为多个块并在这些单独的查询之间显式调用 System.gc()?
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.
在查看您未在帖子中提供的代码和实体后,这不是 ORMLite 问题,而是实体问题.
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.
你有一个照片
的图库
.每张照片都有一个可能很大的字节图像数据数组——可能是 50+k.问题是 Gallery
有一个急切的 Photo
外国集合:
You have a Gallery
of Photo
s. 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 Photo
s:
@ForeignCollectionField(eager = true)
private ForeignCollection<Photo> photos;
然后每个 Photo
都有其父 Gallery
的自动刷新版本.
And then each Photo
has an auto-refreshed version of its parent Gallery
.
@DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = GALLERY)
private Gallery gallery;
这会设置一个急切的获取循环,导致 ORMLite 执行以下操作:
This sets up an eager fetch loop which causes ORMLite to do something like the following:
- 每当 ORMLite 尝试将
Gallery
加载到内存中... - 由于急切收集,它被要求执行另一个查询并将与
画廊
相关联的所有照片加载到内存中. - 对于这些
Photo
实例中的每一个,由于自动刷新的父级,它被要求执行另一个查询以将关联的Gallery
放入内存. - 对于那个
Gallery
,它被要求将所有Photo
加载到内存中. - ... ORMLite 实际上有一个转义,但仍然向下 3 个级别.
- Whenever ORMLite tries to load the
Gallery
into memory... - 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. - For each of those
Photo
instances, it is being asked to do another query to get the associatedGallery
into memory because of the auto-refreshed parent. - And for that
Gallery
it is asked to load all of thePhoto
s into memory. - ... ORMLite actually has an escape but still does this 3 levels down.
ORMLite 没有 Gallery
和 Photo
实例的魔法视图,因此它将父 Gallery
附加到 中的外部字段照片
s.如果你想要这个,那么我会看到下面的 ObjectCache
解决方案.
ORMLite has no magic view of the Gallery
and Photo
instances so it attach the parent Gallery
to the foreign field in the Photo
s. If you want this then I'd see the ObjectCache
solution below.
有多种方法可以解决此问题:
There are a number of ways you can fix this:
- 我建议不要使用
foreignAutoRefresh = true
.如果您需要照片的Gallery
,那么您可以通过执行galleryDao.refresh(photo.getGallery())
来获得它.这打破了急切获取链. - 你也可以让
photos
收藏不变得急切.延迟加载的集合会更多次访问数据库,但也会打破循环. 如果您真的必须拥有所有急切的集合和刷新,那么最好的解决方案是引入
ObjectCache
.您可能需要经常清除缓存,但每个 DAO 都会在缓存中查找并返回相同的对象实体,即使在进行急切获取循环的情况下也是如此.
- I'd recommend not using
foreignAutoRefresh = true
. If you need theGallery
of a photo then you can get it by doinggalleryDao.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();
这篇关于SQLiteException:未知错误(代码 0):本机无法创建新字节 []的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!