8259343: [macOS] Update JNI error handling in Cocoa code.

Reviewed-by: erikj, serb
diff --git a/make/modules/java.desktop/Lib.gmk b/make/modules/java.desktop/Lib.gmk
index 954f093..54b96f5 100644
--- a/make/modules/java.desktop/Lib.gmk
+++ b/make/modules/java.desktop/Lib.gmk
@@ -93,6 +93,7 @@
       LDFLAGS := $(LDFLAGS_JDKLIB) \
           $(call SET_SHARED_LIBRARY_ORIGIN), \
       LIBS := \
+          -ljava \
           -framework Accelerate \
           -framework ApplicationServices \
           -framework AudioToolbox \
@@ -107,6 +108,8 @@
           -framework QuartzCore, \
   ))
 
+  $(BUILD_LIBOSXAPP): $(call FindLib, java.base, java)
+
   TARGETS += $(BUILD_LIBOSXAPP)
 
   ##############################################################################
diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
index eb36724..6f72290 100644
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
@@ -1286,6 +1286,7 @@
 
     array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_firstRectForCharacterRange,
                                 theRange.location); // AWT_THREADING Safe (AWTRunLoopMode)
+    CHECK_EXCEPTION();
 
     _array = (*env)->GetIntArrayElements(env, array, &isCopy);
     if (_array) {
diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m
index e8246be..88c6fb7 100644
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m
@@ -56,7 +56,7 @@
     GET_CPRINTERJOB_CLASS_RETURN(ret); \
     GET_METHOD_RETURN(sjm_getNSPrintInfo, sjc_CPrinterJob, "getNSPrintInfo", "()J", ret);
 
-#define GET_CPRINTERDIALOG_METHOD_RETURN(ret) \
+#define GET_CPRINTERDIALOG_FIELD_RETURN(ret) \
    GET_CPRINTERDIALOG_CLASS_RETURN(ret); \
    GET_FIELD_RETURN(sjm_printerJob, sjc_CPrinterDialog, "fPrinterJob", "Lsun/lwawt/macosx/CPrinterJob;", ret);
 
@@ -651,6 +651,7 @@
 
         // <rdar://problem/4367998> JTable.print attributes are ignored
         jobject pageable = (*env)->CallObjectMethod(env, jthis, jm_getPageable); // AWT_THREADING Safe (!appKit)
+        CHECK_EXCEPTION();
         javaPrinterJobToNSPrintInfo(env, jthis, pageable, printInfo);
 
         PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
@@ -691,11 +692,12 @@
 
     jboolean result = JNI_FALSE;
 JNF_COCOA_ENTER(env);
-    GET_CPRINTERDIALOG_METHOD_RETURN(NO);
+    GET_CPRINTERDIALOG_FIELD_RETURN(NO);
     GET_NSPRINTINFO_METHOD_RETURN(NO)
     jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob);
     if (printerJob == NULL) return NO;
     NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
+    CHECK_EXCEPTION();
     if (printInfo == NULL) return result;
 
     jobject page = (*env)->GetObjectField(env, jthis, jm_page);
@@ -740,7 +742,7 @@
 
     jboolean result = JNI_FALSE;
 JNF_COCOA_ENTER(env);
-    GET_CPRINTERDIALOG_METHOD_RETURN(NO);
+    GET_CPRINTERDIALOG_FIELD_RETURN(NO);
     jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob);
     if (printerJob == NULL) return NO;
     GET_NSPRINTINFO_METHOD_RETURN(NO)
diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m
index 227594d..7f806cc 100644
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m
@@ -24,6 +24,7 @@
  */
 
 #import "GeomUtilities.h"
+#import <JavaNativeFoundation/JavaNativeFoundation.h>
 
 static jobject NewJavaRect(JNIEnv *env, jdouble x, jdouble y, jdouble w, jdouble h) {
     DECLARE_CLASS_RETURN(sjc_Rectangle2DDouble, "java/awt/geom/Rectangle2D$Double", NULL);
@@ -55,10 +56,11 @@
     DECLARE_METHOD_RETURN(jm_rect_getY, sjc_Rectangle2D, "getY", "()D", NSZeroRect);
     DECLARE_METHOD_RETURN(jm_rect_getWidth, sjc_Rectangle2D, "getWidth", "()D", NSZeroRect);
     DECLARE_METHOD_RETURN(jm_rect_getHeight, sjc_Rectangle2D, "getHeight", "()D", NSZeroRect);
-    return NSMakeRect((*env)->CallDoubleMethod(env, rect, jm_rect_getX),
-                      (*env)->CallDoubleMethod(env, rect, jm_rect_getY),
-                      (*env)->CallDoubleMethod(env, rect, jm_rect_getWidth),
-                      (*env)->CallDoubleMethod(env, rect, jm_rect_getHeight));
+    jdouble x = (*env)->CallDoubleMethod(env, rect, jm_rect_getX); CHECK_EXCEPTION();
+    jdouble y = (*env)->CallDoubleMethod(env, rect, jm_rect_getY); CHECK_EXCEPTION();
+    jdouble w = (*env)->CallDoubleMethod(env, rect, jm_rect_getWidth); CHECK_EXCEPTION();
+    jdouble h = (*env)->CallDoubleMethod(env, rect, jm_rect_getHeight); CHECK_EXCEPTION();
+    return NSMakeRect(x, y, w, h);
 }
 
 jobject NSToJavaPoint(JNIEnv *env, NSPoint point) {
@@ -73,9 +75,9 @@
     DECLARE_CLASS_RETURN(sjc_Point2D, "java/awt/geom/Point2D", NSZeroPoint);
     DECLARE_METHOD_RETURN(jm_pt_getX, sjc_Point2D, "getX", "()D", NSZeroPoint);
     DECLARE_METHOD_RETURN(jm_pt_getY, sjc_Point2D, "getY", "()D", NSZeroPoint);
-
-    return NSMakePoint((*env)->CallDoubleMethod(env, point, jm_pt_getX),
-                       (*env)->CallDoubleMethod(env, point, jm_pt_getY));
+    jdouble x = (*env)->CallDoubleMethod(env, point, jm_pt_getX); CHECK_EXCEPTION();
+    jdouble y = (*env)->CallDoubleMethod(env, point, jm_pt_getY); CHECK_EXCEPTION();
+    return NSMakePoint(x, y);
 }
 
 jobject NSToJavaSize(JNIEnv *env, NSSize size) {
@@ -90,14 +92,15 @@
     DECLARE_CLASS_RETURN(sjc_Dimension2D, "java/awt/geom/Dimension2D", NSZeroSize);
     DECLARE_METHOD_RETURN(jm_sz_getWidth, sjc_Dimension2D, "getWidth", "()D", NSZeroSize);
     DECLARE_METHOD_RETURN(jm_sz_getHeight, sjc_Dimension2D, "getHeight", "()D", NSZeroSize);
-
-    return NSMakeSize((*env)->CallDoubleMethod(env, dimension, jm_sz_getWidth),
-                      (*env)->CallDoubleMethod(env, dimension, jm_sz_getHeight));
+    jdouble w = (*env)->CallDoubleMethod(env, dimension, jm_sz_getWidth); CHECK_EXCEPTION();
+    jdouble h = (*env)->CallDoubleMethod(env, dimension, jm_sz_getHeight); CHECK_EXCEPTION();
+    return NSMakeSize(w, h);
 }
 
 static NSScreen *primaryScreen(JNIEnv *env) {
     NSScreen *primaryScreen = [[NSScreen screens] objectAtIndex:0];
     if (primaryScreen != nil) return primaryScreen;
+    if (env != NULL) [JNFException raise:env as:kRuntimeException reason:"Failed to convert, no screen."];
     return nil;
 }
 
diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m
index 04a2909..3f2064c 100644
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m
@@ -640,6 +640,7 @@
         } else {
             AWTView *view = fView;
             jobject jax = (*env)->CallStaticObjectMethod(env, sjc_CAccessible, sjm_getSwingAccessible, fAccessible);
+            CHECK_EXCEPTION();
 
             if ((*env)->IsInstanceOf(env, jax, sjc_Window)) {
                 // In this case jparent is an owner toplevel and we should retrieve its own view
@@ -928,6 +929,7 @@
     if ([(NSNumber*)value boolValue])
     {
         (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestFocus, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
+        CHECK_EXCEPTION();
     }
 }
 
diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m
index 979cd459..d662aae 100644
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m
@@ -160,7 +160,6 @@
 
     DECLARE_STATIC_METHOD_RETURN(jm_getTextRange, sjc_CAccessibleText, "getTextRange",
                     "(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;", nil);
-    CHECK_EXCEPTION();
     jobject jrange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getTextRange,
                        axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent);
     CHECK_EXCEPTION();
diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterView.m
index ef91ed1..5b05989 100644
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterView.m
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterView.m
@@ -123,6 +123,7 @@
     DECLARE_METHOD_RETURN(jm_getJobName, sjc_CPrinterJob, "getJobName", "()Ljava/lang/String;", nil);
 
     jobject o = (*env)->CallObjectMethod(env, fPrinterJob, jm_getJobName); // AWT_THREADING Safe (known object)
+    CHECK_EXCEPTION();
     id result = JNFJavaToNSString(env, o);
     (*env)->DeleteLocalRef(env, o);
     return result;
diff --git a/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h b/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h
index 9ee8f22..4a25ca4 100644
--- a/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h
+++ b/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h
@@ -29,11 +29,24 @@
 #include "jni.h"
 #include "jni_util.h"
 
+#import <Cocoa/Cocoa.h>
+
 /********        LOGGING SUPPORT    *********/
 
 #define LOG_NULL(dst_var, name) \
    if (dst_var == NULL) { \
        NSLog(@"Bad JNI lookup %s\n", name); \
+       NSLog(@"%@",[NSThread callStackSymbols]); \
+       if ([NSThread isMainThread] == NO) { \
+           if ((*env)->ExceptionOccurred(env) == NULL) { \
+              JNU_ThrowInternalError(env, "Bad JNI Lookup"); \
+           } \
+       } else { \
+              if ((*env)->ExceptionOccurred(env) != NULL) { \
+                  (*env)->ExceptionDescribe(env); \
+           } \
+       } \
+       [NSException raise:NSGenericException format:@"JNI Lookup Exception"];  \
     }
 
 /********        GET CLASS SUPPORT    *********/
@@ -147,9 +160,44 @@
 
 /*********       EXCEPTION_HANDLING    *********/
 
+/*
+ * Some explanation to set context of the bigger picture.
+ * Before returning to Java from JNI, NSExceptions are caught - so long as
+ * the body of the native method is wrapped in the ENTER/EXIT macros.
+ * So if we want to directly return to Java from some nested Objective-C
+ * function when detecting a Java exception, we just need to raise an
+ * NSException. Then clear that right before returning to Java,
+ * leaving the Java exception to be seen back in Java-land.
+ *
+ * But if the current thread is the Appkit thread we might as well clear
+ * the Java Exception right now since there's nothing to receive it.
+ * In such a case control will propagate back to the run loop which might
+ * terminate the application. One drawback of that is that the location of
+ * termination does not show where the NSException originated.
+ * And for whatever reason, something swallows that exception.
+ * So as a debugging aid, when on the AppKit thread we can provide a
+ * way (via an env. var.) to log the location.
+ * Additionally provide a similar way to prevent the NSException being
+ * raised and instead just clear the Java Exception.
+ * Together these provide alternate behaviours for more debugging info
+ * or maybe a way for the app to continue running depending on the exact
+ * nature of the problem that has been detected and how survivable it is.
+ */
 #define CHECK_EXCEPTION() \
     if ((*env)->ExceptionOccurred(env) != NULL) { \
-        (*env)->ExceptionClear(env); \
+        if ([NSThread isMainThread] == YES) { \
+            if (getenv("JNU_APPKIT_TRACE")) { \
+                (*env)->ExceptionDescribe(env); \
+                NSLog(@"%@",[NSThread callStackSymbols]); \
+              } else { \
+                  (*env)->ExceptionClear(env); \
+              } \
+         }  \
+        if (getenv("JNU_NO_COCOA_EXCEPTION") == NULL) { \
+            [NSException raise:NSGenericException format:@"Java Exception"]; \
+        } else { \
+            (*env)->ExceptionClear(env); \
+        } \
     };
 
 #define CHECK_EXCEPTION_NULL_RETURN(x, y) \