ndb*_*ent 5 javascript android garbage-collection react-native
我觉得 Android GC、JavaScriptCore 或 Genymotion 中的某个地方可能存在错误。我正在 Android 上测试 React Native 应用程序,所以我的所有代码都是用 JavaScript(而不是 Java)编写的。我试图找出我在以下 Android 模拟器上重现的崩溃:
我注意到我的应用程序在使用大约 5 分钟后总是崩溃。使用 查看日志后adb logcat
,我注意到它总是在 GC 运行后立即崩溃。它只在 Android 上崩溃,而在 iOS 上从未发生过崩溃。它也只有在“远程调试 JS”关闭时才会发生,我才意识到原因。这是因为当启用“远程调试 JS”时,所有 JS 都在我的笔记本电脑上的 Chrome 中运行,在 V8 引擎中。(这使得调试非常困难!)
我正在使用reselect库,但我使用了一个带有可配置“cacheSize”的分支来存储多个结果,而不是仅仅缓存一个结果。你可以在这里看到我的新defaultMemoize
功能。我的第一个想法是我在这里做错了什么,但我没有使用 aWeakMap
或类似的东西。我只是将缓存的结果存储在一个普通数组中,并且我总是持有对选择器的引用,所以我认为 GC 不应该清除内存。
我将描述有关我的应用程序的更多详细信息。我有一个LookupTable
类,它引用一个Matrix
类。查找表预先计算了一些东西以加快查找速度。
我的查找表代码如下所示:
// @flow
import autobind from 'autobind-decorator'
export default class LookupTable {
matrix: Matrix
constructor(state) {
this.generateLookupTable(state)
}
@autobind
valueAt(x: number, y: number) {
this.matrix.get(x, y)
}
@autobind
generateLookupTable() {
// generates the Matrix at this.matrix
}
}
Run Code Online (Sandbox Code Playgroud)
我的原始选择器代码如下所示:
import Immutable from 'immutable'
import { createSelectorCreator, defaultMemoize } from 'reselect'
const createImmutableSelector = (cacheSize = 1, ...args) =>
createSelectorCreator(defaultMemoize, Immutable.is, cacheSize)(...args)
export const lookupTableSelector = createImmutableSelector(3,
firstSelector,
secondSelector,
thirdSelector,
fourthSelector,
(one, two, three, four) =>
new LookupTable(one, two, three, four))
Run Code Online (Sandbox Code Playgroud)
如果您不熟悉reselect
or immutable-js
,我只是在记住一些计算(类似于 lodash 的memoize
),并且我正在使用它Immutable.is
来检查参数相等性。
最后,我会像这样调用选择器:
const lookupTable = lookupTableSelector(state)
const value = lookupTable.valueAt(x, y)
Run Code Online (Sandbox Code Playgroud)
Android GC 运行后,valueAt
导致崩溃,因为this.matrix
未定义。有趣的是,该lookupTable.generateLookupTable
函数也是未定义的。事实上,实例中的所有内容都是未定义的。这就像选择器只是返回一个LookupTable
实例的外壳,所有的数据和方法都消失了。
所以这是我尝试解决的方法:
export const lookupTableSelectorWithoutGCFix = createImmutableSelector(3,
firstSelector,
secondSelector,
thirdSelector,
fourthSelector,
(one, two, three, four) =>
new LookupTable(one, two, three, four))
export const lookupTableSelector = (gameState: Map) => {
const lookupTable = lookupTableSelectorWithoutGCFix(gameState)
if (lookupTable.matrix == null) {
console.warn('LookupTable selector returned an instance with an undefined matrix.' +
'This might be a GC bug on Android. Will clear the cache and generate a new instance.')
lookupTableSelectorWithoutGCFix.clearCache()
return lookupTableSelectorWithoutGCFix(gameState)
}
return lookupTable
}
Run Code Online (Sandbox Code Playgroud)
现在奇怪的是,这段代码从未真正被调用过。我从未在 中看到控制台警告adb logcat
,它也从未在模拟器中显示为黄色框。在此之前,每次 GC 运行后都会发生崩溃。但是在这次更改之后,我通过 5 次 GC 运行测试了该应用程序,一切都运行良好。所以无论我在这里做了什么,我想它改变了 Android GC 的行为,它不再为我的LookupTable
实例清除内存。
你能看出为什么会发生这种情况吗?或者这可能是 Android GC 中的引用计数错误?
归档时间: |
|
查看次数: |
594 次 |
最近记录: |