Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions make/modules/java.desktop/Lib.gmk
Expand Up @@ -93,6 +93,7 @@ ifeq ($(call isTargetOs, macosx), true)
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := \
-ljava \
-framework Accelerate \
-framework ApplicationServices \
-framework AudioToolbox \
Expand All @@ -107,6 +108,8 @@ ifeq ($(call isTargetOs, macosx), true)
-framework QuartzCore, \
))

$(BUILD_LIBOSXAPP): $(call FindLib, java.base, java)

TARGETS += $(BUILD_LIBOSXAPP)

##############################################################################
Expand Down
1 change: 1 addition & 0 deletions src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
Expand Up @@ -1287,6 +1287,7 @@ - (NSRect) firstRectForCharacterRange:(NSRange)theRange actualRange:(NSRangePoin

array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_firstRectForCharacterRange,
theRange.location); // AWT_THREADING Safe (AWTRunLoopMode)
CHECK_EXCEPTION();

_array = (*env)->GetIntArrayElements(env, array, &isCopy);
if (_array) {
Expand Down
8 changes: 5 additions & 3 deletions src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m
Expand Up @@ -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_METHOD_RETURN(sjm_printerJob, sjc_CPrinterDialog, "fPrinterJob", "Lsun/lwawt/macosx/CPrinterJob;", ret);

Expand Down Expand Up @@ -624,6 +624,7 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj

// <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];
Expand Down Expand Up @@ -664,11 +665,12 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj

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);
Expand Down Expand Up @@ -713,7 +715,7 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj

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)
Expand Down
23 changes: 13 additions & 10 deletions src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m
Expand Up @@ -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);
Expand Down Expand Up @@ -55,10 +56,11 @@ NSRect JavaToNSRect(JNIEnv *env, jobject rect) {
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) {
Expand All @@ -73,9 +75,9 @@ NSPoint JavaToNSPoint(JNIEnv *env, jobject point) {
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) {
Expand All @@ -90,14 +92,15 @@ NSSize JavaToNSSize(JNIEnv *env, jobject dimension) {
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;
}

Expand Down
Expand Up @@ -623,6 +623,7 @@ - (id)parent
} 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
Expand Down Expand Up @@ -911,6 +912,7 @@ - (void)accessibilitySetFocusedAttribute:(id)value
if ([(NSNumber*)value boolValue])
{
(*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestFocus, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
CHECK_EXCEPTION();
}
}

Expand Down
Expand Up @@ -160,7 +160,6 @@ - (NSString *)accessibilityValueAttribute

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();
Expand Down
Expand Up @@ -123,6 +123,7 @@ - (NSString*)printJobTitle
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;
Expand Down
50 changes: 49 additions & 1 deletion src/java.desktop/macosx/native/libosxapp/JNIUtilities.h
Expand Up @@ -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 *********/
Expand Down Expand Up @@ -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) \
Expand Down