Bug 959237 - Define GetVM, GetJNIEnv, and GetJNIForThread as infallible; r=blassey
authorJim Chen <nchen@mozilla.com>
Fri, 17 Jan 2014 23:32:24 -0600
changeset 164122 ae1c7e26a97dbb4ae49f78504ec10189982d6dbb
parent 164121 28686e41cdf836698b4388122c0563e1e2e40bf3
child 164123 3f69ca51a4e84d05c6ef1550886a824eb7abf24f
push id26026
push userphilringnalda@gmail.com
push dateSat, 18 Jan 2014 23:17:27 +0000
treeherdermozilla-central@61fd0f987cf2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs959237
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 959237 - Define GetVM, GetJNIEnv, and GetJNIForThread as infallible; r=blassey Currently when either of these methods fail, we log something and rely on the calling code to null check. Since these failures are serious and likely unrecoverable, it's better to define these methods as infallible and just crash if they do fail.
dom/plugins/base/PluginPRLibrary.cpp
dom/plugins/base/android/ANPAudio.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
gfx/thebes/nsSurfaceTexture.cpp
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidJNI.cpp
widget/android/AndroidJNIWrapper.cpp
widget/android/AndroidJavaWrappers.cpp
widget/android/nsWindow.cpp
--- a/dom/plugins/base/PluginPRLibrary.cpp
+++ b/dom/plugins/base/PluginPRLibrary.cpp
@@ -33,18 +33,16 @@ using namespace mozilla::layers;
 
 namespace mozilla {
 #ifdef MOZ_WIDGET_ANDROID
 nsresult
 PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs,
 			       NPPluginFuncs* pFuncs, NPError* error)
 {
   JNIEnv* env = GetJNIForThread();
-  if (!env)
-    return NS_ERROR_FAILURE;
 
   mozilla::AutoLocalJNIFrame jniFrame(env);
 
   if (mNP_Initialize) {
     *error = mNP_Initialize(bFuncs, pFuncs, env);
   } else {
     NP_InitializeFunc pfNP_Initialize = (NP_InitializeFunc)
       PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
--- a/dom/plugins/base/android/ANPAudio.cpp
+++ b/dom/plugins/base/android/ANPAudio.cpp
@@ -120,18 +120,16 @@ public:
 };
 
 NS_IMETHODIMP
 AudioRunnable::Run()
 {
   PR_SetCurrentThreadName("Android Audio");
 
   JNIEnv* jenv = GetJNIForThread();
-  if (!jenv)
-    return NS_ERROR_FAILURE;
 
   mozilla::AutoLocalJNIFrame autoFrame(jenv, 2);
 
   jbyteArray bytearray = jenv->NewByteArray(mTrack->bufferSize);
   if (!bytearray) {
     LOG("AudioRunnable:: Run.  Could not create bytearray");
     return NS_ERROR_FAILURE;
   }
@@ -205,18 +203,16 @@ anp_audio_newTrack(uint32_t sampleRate, 
                    void* user)
 {
   ANPAudioTrack *s = new ANPAudioTrack();
   if (s == nullptr) {
     return nullptr;
   }
 
   JNIEnv *jenv = GetJNIForThread();
-  if (!jenv)
-    return nullptr;
 
   s->at_class = init_jni_bindings(jenv);
   s->rate = sampleRate;
   s->channels = channelCount;
   s->bufferSize = s->rate * s->channels;
   s->isStopped = true;
   s->keepGoing = false;
   s->user = user;
@@ -303,18 +299,16 @@ anp_audio_start(ANPAudioTrack* s)
   }
 
   if (s->keepGoing) {
     // we are already playing.  Ignore.
     return;
   }
 
   JNIEnv *jenv = GetJNIForThread();
-  if (!jenv)
-    return;
 
   mozilla::AutoLocalJNIFrame autoFrame(jenv, 0);
   jenv->CallVoidMethod(s->output_unit, at.play);
 
   if (autoFrame.CheckForException()) {
     jenv->DeleteGlobalRef(s->at_class);
     free(s);
     return;
@@ -333,34 +327,30 @@ anp_audio_start(ANPAudioTrack* s)
 void
 anp_audio_pause(ANPAudioTrack* s)
 {
   if (s == nullptr || s->output_unit == nullptr) {
     return;
   }
 
   JNIEnv *jenv = GetJNIForThread();
-  if (!jenv)
-    return;
 
   mozilla::AutoLocalJNIFrame autoFrame(jenv, 0);
   jenv->CallVoidMethod(s->output_unit, at.pause);
 }
 
 void
 anp_audio_stop(ANPAudioTrack* s)
 {
   if (s == nullptr || s->output_unit == nullptr) {
     return;
   }
 
   s->isStopped = true;
   JNIEnv *jenv = GetJNIForThread();
-  if (!jenv)
-    return;
 
   mozilla::AutoLocalJNIFrame autoFrame(jenv, 0);
   jenv->CallVoidMethod(s->output_unit, at.stop);
 }
 
 bool
 anp_audio_isStopped(ANPAudioTrack* s)
 {
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1564,20 +1564,20 @@ void nsPluginInstanceOwner::ExitFullScre
   // This will cause Paint() to be called, which is where
   // we normally add/update views and layers
   Invalidate();
 }
 
 void nsPluginInstanceOwner::ExitFullScreen(jobject view) {
   JNIEnv* env = AndroidBridge::GetJNIEnv();
 
-  if (env && sFullScreenInstance && sFullScreenInstance->mInstance &&
+  if (sFullScreenInstance && sFullScreenInstance->mInstance &&
       env->IsSameObject(view, (jobject)sFullScreenInstance->mInstance->GetJavaSurface())) {
     sFullScreenInstance->ExitFullScreen();
-  } 
+  }
 }
 
 #endif
 
 nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
 {
 #ifdef MOZ_WIDGET_ANDROID
   if (mInstance) {
--- a/gfx/thebes/nsSurfaceTexture.cpp
+++ b/gfx/thebes/nsSurfaceTexture.cpp
@@ -22,25 +22,22 @@ static int sNextID = 0;
 
 static class JNIFunctions {
 public:
 
   JNIFunctions() : mInitialized(false)
   {
   }
 
-  
   bool EnsureInitialized()
   {
     if (mInitialized)
       return true;
 
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return false;
 
     AutoLocalJNIFrame jniFrame(env);
 
     jSurfaceTextureClass = (jclass)env->NewGlobalRef(env->FindClass("android/graphics/SurfaceTexture"));
     jSurfaceTexture_Ctor = env->GetMethodID(jSurfaceTextureClass, "<init>", "(I)V");
     jSurfaceTexture_updateTexImage = env->GetMethodID(jSurfaceTextureClass, "updateTexImage", "()V");
     jSurfaceTexture_getTransformMatrix = env->GetMethodID(jSurfaceTextureClass, "getTransformMatrix", "([F)V");
 
@@ -49,48 +46,40 @@ public:
   }
 
   jobject CreateSurfaceTexture(GLuint aTexture)
   {
     if (!EnsureInitialized())
       return nullptr;
 
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return nullptr;
 
     AutoLocalJNIFrame jniFrame(env);
 
     return env->NewGlobalRef(env->NewObject(jSurfaceTextureClass, jSurfaceTexture_Ctor, (int) aTexture));
   }
 
   void ReleaseSurfaceTexture(jobject aSurfaceTexture)
   {
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return;
 
     env->DeleteGlobalRef(aSurfaceTexture);
   }
 
   void UpdateTexImage(jobject aSurfaceTexture)
   {
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return;
 
     AutoLocalJNIFrame jniFrame(env);
     env->CallObjectMethod(aSurfaceTexture, jSurfaceTexture_updateTexImage);
   }
 
   bool GetTransformMatrix(jobject aSurfaceTexture, gfx3DMatrix& aMatrix)
   {
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return false;
 
     AutoLocalJNIFrame jniFrame(env);
 
     jfloatArray jarray = env->NewFloatArray(16);
     env->CallVoidMethod(aSurfaceTexture, jSurfaceTexture_getTransformMatrix, jarray);
 
     jfloat* array = env->GetFloatArrayElements(jarray, nullptr);
 
@@ -167,18 +156,16 @@ nsSurfaceTexture::Check()
 
 bool
 nsSurfaceTexture::Init(GLuint aTexture)
 {
   if (!sJNIFunctions.EnsureInitialized())
     return false;
 
   JNIEnv* env = GetJNIForThread();
-  if (!env)
-    return false;
 
   mSurfaceTexture = sJNIFunctions.CreateSurfaceTexture(aTexture);
   if (!mSurfaceTexture)
     return false;
 
   mNativeWindow = AndroidBridge::Bridge()->AcquireNativeWindowFromSurfaceTexture(env, mSurfaceTexture);
 
   mID = ++sNextID;
@@ -199,20 +186,18 @@ nsSurfaceTexture::~nsSurfaceTexture()
   mFrameAvailableCallback = nullptr;
 
   if (mNativeWindow) {
     AndroidBridge::Bridge()->ReleaseNativeWindowForSurfaceTexture(mSurfaceTexture);
     mNativeWindow = nullptr;
   }
 
   JNIEnv* env = GetJNIForThread();
-  if (!env)
-    return;
 
-  if (mSurfaceTexture && env) {
+  if (mSurfaceTexture) {
     GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
 
     env->DeleteGlobalRef(mSurfaceTexture);
     mSurfaceTexture = nullptr;
   }
 }
 
 void*
@@ -254,9 +239,9 @@ nsSurfaceTexture::NotifyFrameAvailable()
       nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &nsSurfaceTexture::NotifyFrameAvailable);
       NS_DispatchToCurrentThread(event);
     } else {
       mFrameAvailableCallback->Run();
     }
   }
 }
 
-#endif // MOZ_WIDGET_ANDROID
\ No newline at end of file
+#endif // MOZ_WIDGET_ANDROID
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -154,16 +154,19 @@ AndroidBridge::ConstructBridge(JNIEnv *j
     sBridge = bridge;
 }
 
 bool
 AndroidBridge::Init(JNIEnv *jEnv)
 {
     ALOG_BRIDGE("AndroidBridge::Init");
     jEnv->GetJavaVM(&mJavaVM);
+    if (!mJavaVM) {
+        MOZ_CRASH(); // Nothing we can do here
+    }
 
     AutoLocalJNIFrame jniFrame(jEnv);
 
     mJNIEnv = nullptr;
     mThread = -1;
     mGLControllerObj = nullptr;
     mOpenedGraphicsLibraries = false;
     mHasNativeBitmapAccess = false;
@@ -264,42 +267,29 @@ jstring AndroidBridge::NewJavaString(Aut
 jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const nsACString& string) {
     return NewJavaString(frame, NS_ConvertUTF8toUTF16(string));
 }
 
 extern "C" {
     __attribute__ ((visibility("default")))
     JNIEnv * GetJNIForThread()
     {
-        JNIEnv *jEnv = nullptr;
-        JavaVM *jVm  = mozilla::AndroidBridge::GetVM();
-        if (!jVm) {
-            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "Returned a null VM");
-            return nullptr;
-        }
-        jEnv = static_cast<JNIEnv*>(PR_GetThreadPrivate(sJavaEnvThreadIndex));
-
-        if (jEnv)
+        JNIEnv *jEnv = static_cast<JNIEnv*>(PR_GetThreadPrivate(sJavaEnvThreadIndex));
+        if (jEnv) {
             return jEnv;
-
-        int status = jVm->GetEnv((void**) &jEnv, JNI_VERSION_1_2);
-        if (status) {
-
-            status = jVm->AttachCurrentThread(&jEnv, nullptr);
-            if (status) {
-                __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread",  "Could not attach");
-                return nullptr;
-            }
-
+        }
+        JavaVM *jVm  = mozilla::AndroidBridge::GetVM();
+        if (!jVm->GetEnv(reinterpret_cast<void**>(&jEnv), JNI_VERSION_1_2) ||
+            !jVm->AttachCurrentThread(&jEnv, nullptr)) {
+            MOZ_ASSERT(jEnv);
             PR_SetThreadPrivate(sJavaEnvThreadIndex, jEnv);
+            return jEnv;
         }
-        if (!jEnv) {
-            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "returning NULL");
-        }
-        return jEnv;
+        MOZ_CRASH();
+        return nullptr; // unreachable
     }
 }
 
 void AutoGlobalWrappedJavaObject::Dispose() {
     if (isNull()) {
         return;
     }
 
@@ -344,18 +334,16 @@ bool
 AndroidBridge::GetHandlersForMimeType(const nsAString& aMimeType,
                                       nsIMutableArray *aHandlersArray,
                                       nsIHandlerApp **aDefaultApp,
                                       const nsAString& aAction)
 {
     ALOG_BRIDGE("AndroidBridge::GetHandlersForMimeType");
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return false;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jobjectArray arr = GeckoAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction);
     if (!arr)
         return false;
 
     jsize len = env->GetArrayLength(arr);
 
@@ -372,18 +360,16 @@ bool
 AndroidBridge::GetHandlersForURL(const nsAString& aURL,
                                  nsIMutableArray* aHandlersArray,
                                  nsIHandlerApp **aDefaultApp,
                                  const nsAString& aAction)
 {
     ALOG_BRIDGE("AndroidBridge::GetHandlersForURL");
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return false;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jobjectArray arr = GeckoAppShell::GetHandlersForURLWrapper(aURL, aAction);
     if (!arr)
         return false;
 
     jsize len = env->GetArrayLength(arr);
 
@@ -396,54 +382,48 @@ AndroidBridge::GetHandlersForURL(const n
 }
 
 void
 AndroidBridge::GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType)
 {
     ALOG_BRIDGE("AndroidBridge::GetMimeTypeFromExtensions");
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstrType = GeckoAppShell::GetMimeTypeFromExtensionsWrapper(NS_ConvertUTF8toUTF16(aFileExt));
     if (!jstrType) {
         return;
     }
     nsJNIString jniStr(jstrType, env);
     CopyUTF16toUTF8(jniStr.get(), aMimeType);
 }
 
 void
 AndroidBridge::GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt)
 {
     ALOG_BRIDGE("AndroidBridge::GetExtensionFromMimeType");
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstrExt = GeckoAppShell::GetExtensionFromMimeTypeWrapper(NS_ConvertUTF8toUTF16(aMimeType));
     if (!jstrExt) {
         return;
     }
     nsJNIString jniStr(jstrExt, env);
     CopyUTF16toUTF8(jniStr.get(), aFileExt);
 }
 
 bool
 AndroidBridge::GetClipboardText(nsAString& aText)
 {
     ALOG_BRIDGE("AndroidBridge::GetClipboardText");
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return false;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jstring result = Clipboard::GetClipboardTextWrapper();
     if (!result)
         return false;
 
     nsJNIString jniStr(result, env);
     aText.Assign(jniStr);
@@ -500,34 +480,30 @@ AndroidBridge::GetScreenDepth()
 
     return sDepth;
 }
 
 void
 AndroidBridge::ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions)
 {
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstr = GeckoAppShell::ShowFilePickerForExtensionsWrapper(aExtensions);
     if (jstr == nullptr) {
         return;
     }
 
     aFilePath.Assign(nsJNIString(jstr, env));
 }
 
 void
 AndroidBridge::ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType)
 {
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstr = GeckoAppShell::ShowFilePickerForMimeTypeWrapper(aMimeType);
     if (jstr == nullptr) {
         return;
     }
 
     aFilePath.Assign(nsJNIString(jstr, env));
@@ -547,18 +523,16 @@ AndroidBridge::Vibrate(const nsTArray<ui
 
     uint32_t len = aPattern.Length();
     if (!len) {
         ALOG_BRIDGE("  invalid 0-length array");
         return;
     }
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
 
     // It's clear if this worth special-casing, but it creates less
     // java junk, so dodges the GC.
     if (len == 1) {
         jlong d = aPattern[0];
         if (d < 0) {
@@ -598,18 +572,16 @@ void
 AndroidBridge::GetSystemColors(AndroidSystemColors *aColors)
 {
 
     NS_ASSERTION(aColors != nullptr, "AndroidBridge::GetSystemColors: aColors is null!");
     if (!aColors)
         return;
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
 
     jintArray arr = GeckoAppShell::GetSystemColoursWrapper();
     if (!arr)
         return;
 
     uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
@@ -636,18 +608,16 @@ void
 AndroidBridge::GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize, uint8_t * const aBuf)
 {
     ALOG_BRIDGE("AndroidBridge::GetIconForExtension");
     NS_ASSERTION(aBuf != nullptr, "AndroidBridge::GetIconForExtension: aBuf is null!");
     if (!aBuf)
         return;
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
 
     jbyteArray arr = GeckoAppShell::GetIconForExtensionWrapper(NS_ConvertUTF8toUTF16(aFileExt), aIconSize);
 
     NS_ASSERTION(arr != nullptr, "AndroidBridge::GetIconForExtension: Returned pixels array is null!");
     if (!arr)
         return;
@@ -708,19 +678,16 @@ EGLSurface
 AndroidBridge::CreateEGLSurfaceForCompositor()
 {
     if (!jEGLSurfacePointerField) {
         return nullptr;
     }
     MOZ_ASSERT(mGLControllerObj, "AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref");
 
     JNIEnv* env = GetJNIForThread(); // called on the compositor thread
-    if (!env) {
-        return nullptr;
-    }
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jobject eglSurface = mGLControllerObj->CreateEGLSurfaceForCompositorWrapper();
     if (!eglSurface)
         return nullptr;
 
     EGLSurface ret = reinterpret_cast<EGLSurface>(env->GetIntField(eglSurface, jEGLSurfacePointerField));
     return ret;
@@ -728,18 +695,16 @@ AndroidBridge::CreateEGLSurfaceForCompos
 
 bool
 AndroidBridge::GetStaticIntField(const char *className, const char *fieldName, int32_t* aInt, JNIEnv* jEnv /* = nullptr */)
 {
     ALOG_BRIDGE("AndroidBridge::GetStaticIntField %s", fieldName);
 
     if (!jEnv) {
         jEnv = GetJNIEnv();
-        if (!jEnv)
-            return false;
     }
 
     initInit();
     getClassGlobalRef(className);
     jfieldID field = getStaticField(fieldName, "I");
 
     if (!field) {
         jEnv->DeleteGlobalRef(jClass);
@@ -754,18 +719,16 @@ AndroidBridge::GetStaticIntField(const c
 
 bool
 AndroidBridge::GetStaticStringField(const char *className, const char *fieldName, nsAString &result, JNIEnv* jEnv /* = nullptr */)
 {
     ALOG_BRIDGE("AndroidBridge::GetStaticStringField %s", fieldName);
 
     if (!jEnv) {
         jEnv = GetJNIEnv();
-        if (!jEnv)
-            return false;
     }
 
     AutoLocalJNIFrame jniFrame(jEnv, 1);
     initInit();
     getClassGlobalRef(className);
     jfieldID field = getStaticField(fieldName, "Ljava/lang/String;");
 
     if (!field) {
@@ -958,36 +921,32 @@ AndroidBridge::ValidateBitmap(jobject bi
         uint32_t format;
         uint32_t flags;
     };
 
     int err;
     struct BitmapInfo info = { 0, };
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return false;
 
     if ((err = AndroidBitmap_getInfo(env, bitmap, &info)) != 0) {
         ALOG_BRIDGE("AndroidBitmap_getInfo failed! (error %d)", err);
         return false;
     }
 
     if ((int)info.width != width || (int)info.height != height)
         return false;
 
     return true;
 }
 
 bool
 AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps)
 {
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return false;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jintArray arr = GeckoAppShell::InitCameraWrapper(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) width, (int32_t) height);
 
     if (!arr)
         return false;
 
     jint *elements = env->GetIntArrayElements(arr, 0);
@@ -1004,18 +963,16 @@ AndroidBridge::InitCamera(const nsCStrin
 }
 
 void
 AndroidBridge::GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
 {
     ALOG_BRIDGE("AndroidBridge::GetCurrentBatteryInformation");
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
 
     // To prevent calling too many methods through JNI, the Java method returns
     // an array of double even if we actually want a double and a boolean.
     jdoubleArray arr = GeckoAppShell::GetCurrentBatteryInformationWrapper();
     if (!arr || env->GetArrayLength(arr) != 3) {
         return;
@@ -1031,18 +988,16 @@ AndroidBridge::GetCurrentBatteryInformat
 }
 
 void
 AndroidBridge::HandleGeckoMessage(const nsAString &aMessage, nsAString &aRet)
 {
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jstring returnMessage = GeckoAppShell::HandleGeckoMessageWrapper(aMessage);
 
     if (!returnMessage)
         return;
 
     nsJNIString jniStr(returnMessage, env);
@@ -1061,18 +1016,16 @@ AndroidBridge::GetSegmentInfoForText(con
 
     dom::mobilemessage::SmsSegmentInfoData data;
 
     data.segments() = 0;
     data.charsPerSegment() = 0;
     data.charsAvailableInLastSegment() = 0;
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return NS_ERROR_FAILURE;
 
     AutoLocalJNIFrame jniFrame(env, 2);
     jstring jText = NewJavaString(&jniFrame, aText);
     jobject obj = env->CallStaticObjectMethod(mAndroidSmsMessageClass,
                                               jCalculateLength, jText, JNI_FALSE);
     if (jniFrame.CheckForException())
         return NS_ERROR_FAILURE;
 
@@ -1136,18 +1089,16 @@ AndroidBridge::DeleteMessage(int32_t aMe
 
 void
 AndroidBridge::CreateMessageList(const dom::mobilemessage::SmsFilterData& aFilter, bool aReverse,
                                  nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::CreateMessageList");
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
     AutoLocalJNIFrame jniFrame(env, 2);
 
     jobjectArray numbers =
@@ -1214,18 +1165,16 @@ AndroidBridge::DequeueSmsRequest(uint32_
 }
 
 void
 AndroidBridge::GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo)
 {
     ALOG_BRIDGE("AndroidBridge::GetCurrentNetworkInformation");
 
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 1);
 
     // To prevent calling too many methods through JNI, the Java method returns
     // an array of double even if we actually want a double, two booleans, and an integer.
 
     jdoubleArray arr = GeckoAppShell::GetCurrentNetworkInformationWrapper();
     if (!arr || env->GetArrayLength(arr) != 4) {
@@ -1241,18 +1190,16 @@ AndroidBridge::GetCurrentNetworkInformat
 
     env->ReleaseDoubleArrayElements(arr, info, 0);
 }
 
 void *
 AndroidBridge::LockBitmap(jobject bitmap)
 {
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return nullptr;
 
     AutoLocalJNIFrame jniFrame(env, 0);
 
     int err;
     void *buf;
 
     if ((err = AndroidBitmap_lockPixels(env, bitmap, &buf)) != 0) {
         ALOG_BRIDGE("AndroidBitmap_lockPixels failed! (error %d)", err);
@@ -1261,18 +1208,16 @@ AndroidBridge::LockBitmap(jobject bitmap
 
     return buf;
 }
 
 void
 AndroidBridge::UnlockBitmap(jobject bitmap)
 {
     JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env, 0);
 
     int err;
 
     if ((err = AndroidBitmap_unlockPixels(env, bitmap)) != 0)
         ALOG_BRIDGE("AndroidBitmap_unlockPixels failed! (error %d)", err);
 }
@@ -1410,18 +1355,16 @@ AndroidBridge::LockWindow(void *window, 
 
     return true;
 }
 
 jobject
 AndroidBridge::GetGlobalContextRef() {
     if (sGlobalContext == nullptr) {
         JNIEnv *env = GetJNIForThread();
-        if (!env)
-            return 0;
 
         AutoLocalJNIFrame jniFrame(env, 4);
 
         jobject context = GeckoAppShell::GetContext();
         if (!context) {
             ALOG_BRIDGE("%s: Could not GetContext()", __FUNCTION__);
             return 0;
         }
@@ -1642,18 +1585,16 @@ AndroidBridge::ScheduleComposite()
 nsresult
 AndroidBridge::GetProxyForURI(const nsACString & aSpec,
                               const nsACString & aScheme,
                               const nsACString & aHost,
                               const int32_t      aPort,
                               nsACString & aResult)
 {
     JNIEnv* env = GetJNIEnv();
-    if (!env)
-        return NS_ERROR_FAILURE;
 
     AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstrRet = GeckoAppShell::GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec),
                                             NS_ConvertUTF8toUTF16(aScheme),
                                             NS_ConvertUTF8toUTF16(aHost),
                                             aPort);
 
     if (!jstrRet)
@@ -1694,18 +1635,16 @@ extern "C"
 __attribute__ ((visibility("default")))
 jobject JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size);
 
 bool
 AndroidBridge::GetThreadNameJavaProfiling(uint32_t aThreadId, nsCString & aResult)
 {
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-        return false;
 
     AutoLocalJNIFrame jniFrame(env, 1);
 
     jstring jstrThreadName = GeckoJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId);
 
     if (!jstrThreadName)
         return false;
 
@@ -1714,18 +1653,16 @@ AndroidBridge::GetThreadNameJavaProfilin
     return true;
 }
 
 bool
 AndroidBridge::GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId,
                                           uint32_t aFrameId, nsCString & aResult)
 {
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-        return false;
 
     AutoLocalJNIFrame jniFrame(env, 1);
 
     jstring jstrSampleName = GeckoJavaSampler::GetFrameNameJavaProfilingWrapper(aThreadId, aSampleId, aFrameId);
 
     if (!jstrSampleName)
         return false;
 
@@ -1772,18 +1709,16 @@ nsresult AndroidBridge::CaptureThumbnail
         srcW = width;
         srcH = width / aspectRatio;
     } else {
         srcW = height * aspectRatio;
         srcH = height;
     }
 
     JNIEnv* env = GetJNIEnv();
-    if (!env)
-        return NS_ERROR_FAILURE;
 
     AutoLocalJNIFrame jniFrame(env, 0);
 
     nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
     if (!win)
         return NS_ERROR_FAILURE;
     nsRefPtr<nsPresContext> presContext;
     nsIDocShell* docshell = win->GetDocShell();
@@ -1842,17 +1777,17 @@ nsresult AndroidBridge::CaptureThumbnail
 }
 
 void
 AndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort)
 {
 
     ALOG_BRIDGE("Enter: %s", __PRETTY_FUNCTION__);
     JNIEnv* env = GetJNIEnv();
-    if (!env || !mLayerClient || mLayerClient->isNull()) {
+    if (!mLayerClient || mLayerClient->isNull()) {
 
         ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return;
     }
     AutoLocalJNIFrame jniFrame(env, 0);
 
     float x, y, width, height,
         pageLeft, pageTop, pageRight, pageBottom,
@@ -1910,18 +1845,17 @@ AndroidBridge::ContentDocumentChanged()
         return;
     }
     mLayerClient->ContentDocumentChanged();
 }
 
 bool
 AndroidBridge::IsContentDocumentDisplayed()
 {
-    JNIEnv* env = GetJNIEnv();
-    if (!env || !mLayerClient)
+    if (!mLayerClient)
         return false;
 
     return mLayerClient->IsContentDocumentDisplayed();
 }
 
 bool
 AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, ScreenRect& aCompositionBounds, CSSToScreenScale& aZoom)
 {
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -136,34 +136,28 @@ public:
 
     static void ConstructBridge(JNIEnv *jEnv);
 
     static AndroidBridge *Bridge() {
         return sBridge.get();
     }
 
     static JavaVM *GetVM() {
-        if (MOZ_LIKELY(sBridge))
-            return sBridge->mJavaVM;
-        return nullptr;
+        MOZ_ASSERT(sBridge);
+        return sBridge->mJavaVM;
     }
 
+
     static JNIEnv *GetJNIEnv() {
-        if (MOZ_LIKELY(sBridge)) {
-            if (!pthread_equal(pthread_self(), sBridge->mThread)) {
-                __android_log_print(ANDROID_LOG_INFO, "AndroidBridge",
-                                    "###!!!!!!! Something's grabbing the JNIEnv from the wrong thread! (thr %p should be %p)",
-                                    (void*)pthread_self(), (void*)sBridge->mThread);
-                MOZ_ASSERT(false, "###!!!!!!! Something's grabbing the JNIEnv from the wrong thread!");
-                return nullptr;
-            }
-            return sBridge->mJNIEnv;
-
+        MOZ_ASSERT(sBridge);
+        if (MOZ_UNLIKELY(!pthread_equal(pthread_self(), sBridge->mThread))) {
+            MOZ_CRASH();
         }
-        return nullptr;
+        MOZ_ASSERT(sBridge->mJNIEnv);
+        return sBridge->mJNIEnv;
     }
 
     // The bridge needs to be constructed via ConstructBridge first,
     // and then once the Gecko main thread is spun up (Gecko side),
     // SetMainThread should be called which will create the JNIEnv for
     // us to use.  toolkit/xre/nsAndroidStartup.cpp calls
     // SetMainThread.
     bool SetMainThread(pthread_t thr);
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -776,21 +776,16 @@ NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_onFullScreenPluginHidden(JNIEnv* jenv, jclass, jobject view)
 {
   class ExitFullScreenRunnable : public nsRunnable {
     public:
       ExitFullScreenRunnable(jobject view) : mView(view) {}
 
       NS_IMETHODIMP Run() {
         JNIEnv* env = AndroidBridge::GetJNIEnv();
-        if (!env) {
-          NS_WARNING("Failed to acquire JNI env, can't exit plugin fullscreen mode");
-          return NS_OK;
-        }
-
         nsPluginInstanceOwner::ExitFullScreen(mView);
         env->DeleteGlobalRef(mView);
         return NS_OK;
       }
 
     private:
       jobject mView;
   };
--- a/widget/android/AndroidJNIWrapper.cpp
+++ b/widget/android/AndroidJNIWrapper.cpp
@@ -32,17 +32,16 @@ class GetGlobalClassRefRunnable : public
 extern "C" {
   __attribute__ ((visibility("default")))
   jclass
   jsjni_FindClass(const char *className) {
     // FindClass outside the main thread will run into problems due
     // to missing the classpath
     MOZ_ASSERT(NS_IsMainThread());
     JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv();
-    if (!env) return nullptr;
     return env->FindClass(className);
   }
 
   jclass
   __jsjni_GetGlobalClassRef(const char *className) {
     // root class globally
     JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv();
     jclass globalRef = static_cast<jclass>(env->NewGlobalRef(env->FindClass(className)));
@@ -71,47 +70,43 @@ extern "C" {
   }
 
   __attribute__ ((visibility("default")))
   jmethodID
   jsjni_GetStaticMethodID(jclass methodClass,
                           const char *methodName,
                           const char *signature) {
     JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv();
-    if (!env) return nullptr;
     return env->GetStaticMethodID(methodClass, methodName, signature);
   }
 
   __attribute__ ((visibility("default")))
   bool
   jsjni_ExceptionCheck() {
     JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv();
-    if (!env) return nullptr;
     return env->ExceptionCheck();
   }
 
   __attribute__ ((visibility("default")))
   void
   jsjni_CallStaticVoidMethodA(jclass cls,
                               jmethodID method,
                               jvalue *values) {
     JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv();
-    if (!env) return;
 
     mozilla::AutoLocalJNIFrame jniFrame(env);
     env->CallStaticVoidMethodA(cls, method, values);
   }
 
   __attribute__ ((visibility("default")))
   int
   jsjni_CallStaticIntMethodA(jclass cls,
                              jmethodID method,
                              jvalue *values) {
     JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv();
-    if (!env) return -1;
 
     mozilla::AutoLocalJNIFrame jniFrame(env);
     return env->CallStaticIntMethodA(cls, method, values);
   }
 
   __attribute__ ((visibility("default")))
   jobject jsjni_GetGlobalContextRef() {
     return mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -963,20 +963,16 @@ nsJNIString::nsJNIString(jstring jstr, J
 {
     if (!jstr) {
         SetIsVoid(true);
         return;
     }
     JNIEnv *jni = jenv;
     if (!jni) {
         jni = AndroidBridge::GetJNIEnv();
-        if (!jni) {
-            SetIsVoid(true);
-            return;
-        }
     }
     const jchar* jCharPtr = jni->GetStringChars(jstr, nullptr);
 
     if (!jCharPtr) {
         SetIsVoid(true);
         return;
     }
 
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -1054,19 +1054,16 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
     if (!mIsVisible) {
         ALOG("##### redraw for window %p, which is not visible -- ignoring!", (void*) this);
         DumpWindows();
         return;
     }
 
     nsRefPtr<nsWindow> kungFuDeathGrip(this);
 
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
-    if (!env)
-        return;
     AutoLocalJNIFrame jniFrame;
 
     // We're paused, or we haven't been given a window-size yet, so do nothing
     if (sCompositorPaused || gAndroidBounds.width <= 0 || gAndroidBounds.height <= 0) {
         return;
     }
 
     int bytesPerPixel = 2;
@@ -2353,19 +2350,16 @@ nsWindow::GetIMEUpdatePreference()
                             nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE);
     return nsIMEUpdatePreference(notifications, true);
 }
 
 void
 nsWindow::DrawWindowUnderlay(LayerManagerComposite* aManager, nsIntRect aRect)
 {
     JNIEnv *env = GetJNIForThread();
-    NS_ABORT_IF_FALSE(env, "No JNI environment at DrawWindowUnderlay()!");
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env);
 
     GeckoLayerClient* client = AndroidBridge::Bridge()->GetLayerClient();
     if (!client || client->isNull()) {
         ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return;
     }
@@ -2392,19 +2386,16 @@ nsWindow::DrawWindowUnderlay(LayerManage
     client->DeactivateProgram(); // redundant, but in case somebody adds code after this...
 }
 
 void
 nsWindow::DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect)
 {
     PROFILER_LABEL("nsWindow", "DrawWindowOverlay");
     JNIEnv *env = GetJNIForThread();
-    NS_ABORT_IF_FALSE(env, "No JNI environment at DrawWindowOverlay()!");
-    if (!env)
-        return;
 
     AutoLocalJNIFrame jniFrame(env);
 
     NS_ABORT_IF_FALSE(!mLayerRendererFrame.isNull(),
                       "Frame should have been created in DrawWindowUnderlay()!");
 
     GeckoLayerClient* client = AndroidBridge::Bridge()->GetLayerClient();