Trigger GC and drop compiled code on low memory

Reviewed By: astreet

Differential Revision: D2658693

fb-gh-sync-id: 8cba49b67ac45a2dbf8b4c9c404d6fb9c97693f6
This commit is contained in:
Alexander Blom
2015-12-07 08:43:24 -08:00
committed by facebook-github-bot-5
parent 611e0619ca
commit 510d50fc17
12 changed files with 182 additions and 3 deletions

View File

@@ -0,0 +1,93 @@
// Copyright 2004-present Facebook. All Rights Reserved.
package com.facebook.react;
import javax.annotation.Nullable;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.MemoryPressure;
import com.facebook.react.bridge.ReactContext;
import static android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
import static android.content.ComponentCallbacks2.TRIM_MEMORY_MODERATE;
import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
/**
* Translates and routes memory pressure events to the current catalyst instance.
*/
public class MemoryPressureRouter {
// Trigger this by sending an intent to your activity with adb shell:
// am start -a "com.facebook.catalyst.ACTION_TRIM_MEMORY" --activity-single-top -n <activity>
private static final String ACTION_TRIM_MEMORY ="com.facebook.catalyst.ACTION_TRIM_MEMORY";
private @Nullable CatalystInstance mCatalystInstance;
private final ComponentCallbacks2 mCallbacks = new ComponentCallbacks2() {
@Override
public void onTrimMemory(int level) {
trimMemory(level);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
}
@Override
public void onLowMemory() {
}
};
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static boolean handleDebugIntent(Activity activity, String action) {
switch (action) {
case ACTION_TRIM_MEMORY:
simulateTrimMemory(activity, TRIM_MEMORY_MODERATE);
break;
default:
return false;
}
return true;
}
MemoryPressureRouter(Context context) {
context.getApplicationContext().registerComponentCallbacks(mCallbacks);
}
public void onNewReactContextCreated(ReactContext reactContext) {
mCatalystInstance = reactContext.getCatalystInstance();
}
public void onReactInstanceDestroyed() {
mCatalystInstance = null;
}
public void destroy(Context context) {
context.getApplicationContext().unregisterComponentCallbacks(mCallbacks);
}
private void trimMemory(int level) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
dispatchMemoryPressure(MemoryPressure.CRITICAL);
} else if (level >= TRIM_MEMORY_BACKGROUND || level == TRIM_MEMORY_RUNNING_CRITICAL) {
dispatchMemoryPressure(MemoryPressure.MODERATE);
}
}
private void dispatchMemoryPressure(MemoryPressure level) {
if (mCatalystInstance != null) {
mCatalystInstance.handleMemoryPressure(level);
}
}
private static void simulateTrimMemory(Activity activity, int level) {
activity.getApplication().onTrimMemory(level);
activity.onTrimMemory(level);
}
}

View File

@@ -100,6 +100,7 @@ import com.facebook.systrace.Systrace;
new ConcurrentLinkedQueue<>();
private volatile boolean mHasStartedCreatingInitialContext = false;
private final UIImplementationProvider mUIImplementationProvider;
private final MemoryPressureRouter mMemoryPressureRouter;
private final ReactInstanceDevCommandsHandler mDevInterface =
new ReactInstanceDevCommandsHandler() {
@@ -215,6 +216,7 @@ import com.facebook.systrace.Systrace;
mBridgeIdleDebugListener = bridgeIdleDebugListener;
mLifecycleState = initialLifecycleState;
mUIImplementationProvider = uiImplementationProvider;
mMemoryPressureRouter = new MemoryPressureRouter(applicationContext);
}
@Override
@@ -400,6 +402,7 @@ import com.facebook.systrace.Systrace;
public void onDestroy() {
UiThreadUtil.assertOnUiThread();
mMemoryPressureRouter.destroy(mApplicationContext);
if (mUseDeveloperSupport) {
mDevSupportManager.setDevSupportEnabled(false);
}
@@ -539,6 +542,7 @@ import com.facebook.systrace.Systrace;
catalystInstance.initialize();
mDevSupportManager.onNewReactContextCreated(reactContext);
mMemoryPressureRouter.onNewReactContextCreated(reactContext);
moveReactContextToCurrentLifecycleState(reactContext);
for (ReactRootView rootView : mAttachedRootViews) {
@@ -591,6 +595,7 @@ import com.facebook.systrace.Systrace;
}
reactContext.onDestroy();
mDevSupportManager.onReactInstanceDestroyed(reactContext);
mMemoryPressureRouter.onReactInstanceDestroyed();
}
/**

View File

@@ -9,8 +9,6 @@
package com.facebook.react.bridge;
import javax.annotation.Nullable;
import java.util.Collection;
import com.facebook.react.bridge.queue.CatalystQueueConfiguration;
@@ -49,6 +47,8 @@ public interface CatalystInstance {
<T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface);
Collection<NativeModule> getNativeModules();
void handleMemoryPressure(MemoryPressure level);
/**
* Adds a idle listener for this Catalyst instance. The listener will receive notifications
* whenever the bridge transitions from idle to busy and vice-versa, where the busy state is

View File

@@ -314,6 +314,11 @@ public class CatalystInstanceImpl implements CatalystInstance {
return mJavaRegistry.getAllModules();
}
@Override
public void handleMemoryPressure(MemoryPressure level) {
Assertions.assertNotNull(mBridge).handleMemoryPressure(level);
}
/**
* Adds a idle listener for this Catalyst instance. The listener will receive notifications
* whenever the bridge transitions from idle to busy and vice-versa, where the busy state is

View File

@@ -0,0 +1,8 @@
// Copyright 2004-present Facebook. All Rights Reserved.
package com.facebook.react.bridge;
public enum MemoryPressure {
MODERATE,
CRITICAL
}

View File

@@ -56,6 +56,19 @@ public class ReactBridge extends Countable {
super.dispose();
}
public void handleMemoryPressure(MemoryPressure level) {
switch (level) {
case MODERATE:
handleMemoryPressureModerate();
break;
case CRITICAL:
handleMemoryPressureCritical();
break;
default:
throw new IllegalArgumentException("Unknown level: " + level);
}
}
private native void initialize(
JavaScriptExecutor jsExecutor,
ReactCallback callback,
@@ -72,4 +85,6 @@ public class ReactBridge extends Countable {
public native boolean supportsProfiling();
public native void startProfiler(String title);
public native void stopProfiler(String title, String filename);
private native void handleMemoryPressureModerate();
private native void handleMemoryPressureCritical();
}