I feel that there might be a bug somewhere in Android GC, JavaScriptCore, or perhaps in Genymotion. I am testing a React Native application on Android, so all my code is written in JavaScript (not Java). I am trying to figure out what crash I reproduced on the following Android emulators:
- Samsung Galaxy S6 - 6.0.0 - API 23
- Google Nexus 5X - 7.1.0 - API 25
I noticed that my application always crashed after I used it for about 5 minutes. Looking at the logs with adb logcat, I noticed that it always crashes immediately after starting the GC. It was just a crash on Android, and the crash never happened on iOS. This also happened when JS Debugging Remotely was disabled, and I just realized why. This is because when "JS Debugging remotely" is turned on, all JS runs inside Chrome on my laptop in the V8 engine . (Because of which it is quite difficult to debug!)
I use the reselect library , but I use the custom branch "cacheSize" to store multiple results, instead of just caching a single result. You can see my new feature defaultMemoizehere . My first thought is that I did something wrong, but I do not use WeakMapor something like that. I just store the cached results in a regular array, and I always keep a reference to the selector, so I don't think GC should clear the memory.
I will talk about some of the details of my application. I have a class LookupTablethat references a class Matrix. The lookup table pre-computes some things for faster searches.
My view table code looks something like this:
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() {
}
}
:
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))
reselect immutable-js, ( lodash memoize), Immutable.is .
, :
const lookupTable = lookupTableSelector(state)
const value = lookupTable.valueAt(x, y)
Android GC valueAt , this.matrix undefined. , lookupTable.generateLookupTable undefined. , undefined. 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
}
, . adb logcat, . GC. 5 GC, . , , , Android GC, LookupTable.
, ? , , Android GC?