From df3ba5f7d6bbfc77f2049e8fb8b303b4664506ca Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Wed, 3 Apr 2024 13:48:53 +0200 Subject: [PATCH 1/5] feat: Trigger Java GC on reload --- .../com/facebook/react/devsupport/BridgeDevSupportManager.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java index e0f831b7a87e..c775ba0ab43a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java @@ -194,6 +194,9 @@ public void handleReloadJS() { ReactMarkerConstants.RELOAD, getDevSettings().getPackagerConnectionSettings().getDebugServerHost()); + // maybe trigger garbage-collector + System.gc(); + // dismiss redbox if exists hideRedboxDialog(); From d7579de561344b5f97924fed963847d73fc584f2 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Wed, 3 Apr 2024 13:50:30 +0200 Subject: [PATCH 2/5] fix: Also do for bridgeless --- .../facebook/react/runtime/BridgelessDevSupportManager.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java index e71937dd6d7f..c92df79d2cdc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java @@ -99,6 +99,9 @@ public void onError(String url, Throwable cause) { public void handleReloadJS() { UiThreadUtil.assertOnUiThread(); + // maybe trigger garbage-collector + System.gc(); + // dismiss redbox if exists hideRedboxDialog(); mReactHost.reload("BridgelessDevSupportManager.handleReloadJS()"); From 9ee0da2715c7fd0c898a564e6cf606cd7144a77a Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Wed, 3 Apr 2024 13:58:03 +0200 Subject: [PATCH 3/5] fix: Trigger `gc()` _after_ reload, not _before_ --- .../facebook/react/devsupport/BridgeDevSupportManager.java | 6 +++--- .../facebook/react/runtime/BridgelessDevSupportManager.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java index c775ba0ab43a..abd63d10d6f2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java @@ -194,9 +194,6 @@ public void handleReloadJS() { ReactMarkerConstants.RELOAD, getDevSettings().getPackagerConnectionSettings().getDebugServerHost()); - // maybe trigger garbage-collector - System.gc(); - // dismiss redbox if exists hideRedboxDialog(); @@ -213,6 +210,9 @@ public void handleReloadJS() { .getDevServerBundleURL(Assertions.assertNotNull(getJSAppBundleName())); reloadJSFromServer(bundleURL); } + + // maybe trigger garbage-collector + System.gc(); } /** Starts of stops the sampling profiler */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java index c92df79d2cdc..a76978039174 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java @@ -99,9 +99,6 @@ public void onError(String url, Throwable cause) { public void handleReloadJS() { UiThreadUtil.assertOnUiThread(); - // maybe trigger garbage-collector - System.gc(); - // dismiss redbox if exists hideRedboxDialog(); mReactHost.reload("BridgelessDevSupportManager.handleReloadJS()"); @@ -111,6 +108,9 @@ public void handleReloadJS() { String bundleURL = getDevServerHelper().getDevServerBundleURL(Assertions.assertNotNull(getJSAppBundleName())); reloadJSFromServer(bundleURL); + + // maybe trigger garbage-collector + System.gc(); } private static ReactInstanceDevHelper createInstanceDevHelper(final ReactHostImpl reactHost) { From d3b704991de01989776bf2e870c3d4259577a043 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Wed, 3 Apr 2024 15:52:35 +0200 Subject: [PATCH 4/5] chore: Move GC call to `ReactInstanceManager::recreateReactContextInBackground` --- .../main/java/com/facebook/react/ReactInstanceManager.java | 7 +++++++ .../facebook/react/devsupport/BridgeDevSupportManager.java | 3 --- .../react/runtime/BridgelessDevSupportManager.java | 3 --- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 7eed8007bfb5..344f90d86332 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -443,6 +443,13 @@ public void recreateReactContextInBackground() { "recreateReactContextInBackground should only be called after the initial " + "createReactContextInBackground call."); recreateReactContextInBackgroundInner(); + + // If some JNI types (e.g. jni::HybridClass) are used in JSI (e.g. jsi::HostObject), they might + // not be immediately deleted on an app refresh as both Java and JavaScript are + // garbage-collected languages and the memory might float around for a while. + // For C++ developers, this will be hard to debug as destructors might be called at a later point, + // so in this case we trigger a Java GC to maybe eagerly collect such objects when the app reloads. + System.gc(); } @ThreadConfined(UI) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java index abd63d10d6f2..e0f831b7a87e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java @@ -210,9 +210,6 @@ public void handleReloadJS() { .getDevServerBundleURL(Assertions.assertNotNull(getJSAppBundleName())); reloadJSFromServer(bundleURL); } - - // maybe trigger garbage-collector - System.gc(); } /** Starts of stops the sampling profiler */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java index a76978039174..e71937dd6d7f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessDevSupportManager.java @@ -108,9 +108,6 @@ public void handleReloadJS() { String bundleURL = getDevServerHelper().getDevServerBundleURL(Assertions.assertNotNull(getJSAppBundleName())); reloadJSFromServer(bundleURL); - - // maybe trigger garbage-collector - System.gc(); } private static ReactInstanceDevHelper createInstanceDevHelper(final ReactHostImpl reactHost) { From 417a2b28d8ac18e303b8e9260a4f7916f9f0d966 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 4 Apr 2024 11:27:45 +0200 Subject: [PATCH 5/5] fix: Move into `onReactInstanceDestroyed(..)` --- .../main/java/com/facebook/react/ReactInstanceManager.java | 7 ------- .../facebook/react/devsupport/DevSupportManagerBase.java | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 344f90d86332..7eed8007bfb5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -443,13 +443,6 @@ public void recreateReactContextInBackground() { "recreateReactContextInBackground should only be called after the initial " + "createReactContextInBackground call."); recreateReactContextInBackgroundInner(); - - // If some JNI types (e.g. jni::HybridClass) are used in JSI (e.g. jsi::HostObject), they might - // not be immediately deleted on an app refresh as both Java and JavaScript are - // garbage-collected languages and the memory might float around for a while. - // For C++ developers, this will be hard to debug as destructors might be called at a later point, - // so in this case we trigger a Java GC to maybe eagerly collect such objects when the app reloads. - System.gc(); } @ThreadConfined(UI) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java index 5da3374ca46b..d49d04d6f0c8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -605,6 +605,13 @@ public void onReactInstanceDestroyed(ReactContext reactContext) { // for this manager resetCurrentContext(null); } + + // If some JNI types (e.g. jni::HybridClass) are used in JSI (e.g. jsi::HostObject), they might + // not be immediately deleted on an app refresh as both Java and JavaScript are + // garbage-collected languages and the memory might float around for a while. + // For C++ developers, this will be hard to debug as destructors might be called at a later point, + // so in this case we trigger a Java GC to maybe eagerly collect such objects when the app reloads. + System.gc(); } @Override