Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
@@ -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 \
@@ -107,6 +108,8 @@ ifeq ($(call isTargetOs, macosx), true)
-framework QuartzCore, \
))

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

TARGETS += $(BUILD_LIBOSXAPP)

##############################################################################
@@ -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) {
@@ -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);

@@ -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];
@@ -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);
@@ -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)
@@ -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 @@ 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) {
@@ -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) {
@@ -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;
}

@@ -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
@@ -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();
}
}

@@ -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();
@@ -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;
@@ -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) \