Skip to content

should android onTrimMemory() events trigger JavaScript garbage collection? #27532

@jgreen210

Description

@jgreen210

Android has an event that is fired if memory is low:

https://developer.android.com/reference/android/content/ComponentCallbacks2.html#onTrimMemory(int)

React native is listening to it here:

https://github.com/facebook/react-native/blob/v0.61.5/ReactAndroid/src/main/java/com/facebook/react/MemoryPressureRouter.java

Other code in react native can register to listen to the event. Currently, there is just one listener:

https://github.com/facebook/react-native/blob/v0.61.5/ReactAndroid/src/main/java/com/facebook/react/bridge/MemoryPressureListener.java

...that is registered from the CatalystInstance:

$ fgrep -ri handleMemoryPressure .
./ReactCommon/cxxreact/NativeToJsBridge.h:  void handleMemoryPressure(int pressureLevel);
./ReactCommon/cxxreact/JSExecutor.h:  virtual void handleMemoryPressure(__unused int pressureLevel) {}
./ReactCommon/cxxreact/NativeToJsBridge.cpp:void NativeToJsBridge::handleMemoryPressure(int pressureLevel) {
./ReactCommon/cxxreact/NativeToJsBridge.cpp:    executor->handleMemoryPressure(pressureLevel);
./ReactCommon/cxxreact/Instance.h:  void handleMemoryPressure(int pressureLevel);
./ReactCommon/cxxreact/Instance.cpp:void Instance::handleMemoryPressure(int pressureLevel) {
./ReactCommon/cxxreact/Instance.cpp:  nativeToJsBridge_->handleMemoryPressure(pressureLevel);
./ReactAndroid/src/main/java/com/facebook/react/MemoryPressureRouter.java:    // themselves in handleMemoryPressure()
./ReactAndroid/src/main/java/com/facebook/react/MemoryPressureRouter.java:      listener.handleMemoryPressure(level);
./ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java:  private native void jniHandleMemoryPressure(int level);
./ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java:  public void handleMemoryPressure(int level) {
./ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java:    jniHandleMemoryPressure(level);
./ReactAndroid/src/main/java/com/facebook/react/bridge/MemoryPressureListener.java:  void handleMemoryPressure(int level);
./ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h:  void handleMemoryPressure(int pressureLevel);
./ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp:    makeNativeMethod("jniHandleMemoryPressure", CatalystInstanceImpl::handleMemoryPressure),
./ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp:void CatalystInstanceImpl::handleMemoryPressure(int pressureLevel) {
./ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp:  instance_->handleMemoryPressure(pressureLevel);

The CatalystInstance implementation is:

https://github.com/facebook/react-native/blob/v0.61.5/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java#L506

This delegates the event via:

ReactCommon/cxxreact/Instance.cpp
ReactCommon/cxxreact/NativeToJsBridge.cpp

...finally calling:

https://github.com/facebook/react-native/blob/v0.61.5/ReactCommon/cxxreact/JSExecutor.h#L106

virtual void handleMemoryPressure(__unused int pressureLevel) {}

I don't see anything overriding this in the react-native, hermes, https://www.npmjs.com/package/jsc-android or JavaScriptCore repos, so (just from this code inspection) it looks like the onTrimMemory() event is ignored.

I think it would be useful to connect it up to JavaScript garbage collection. E.g. it would stop garbage-collectable js blob handles from holding on to BlobModule.java HashMap entries and could avoid the java OutOfMemoryErrors that are theoretically still possible even after this fix:

766f470

Hermes has a method for triggering garbage collection:

https://github.com/facebook/hermes/blob/v0.2.1/API/hermes/hermes.cpp#L489

...implementing a collectGarbage() in the jsi API:

https://github.com/facebook/react-native/blob/v0.61.5/ReactCommon/jsi/jsi/instrumentation.h#L47

Would need to find a suitable onTrimMemory() level. Would maybe need to make sure that use correct thread to trigger garbage collection.

React Native version:

react: 16.9.0 => 16.9.0
react-native: 0.61.5 => 0.61.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugPlatform: AndroidAndroid applications.StaleThere has been a lack of activity on this issue and it may be closed soon.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions