8259343: [macOS] Update JNI error handling in Cocoa code.
Reviewed-by: erikj, serb
This commit is contained in:
parent
c338f1167f
commit
d6a2105b5c
@ -93,6 +93,7 @@ ifeq ($(call isTargetOs, macosx), true)
|
|||||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||||
LIBS := \
|
LIBS := \
|
||||||
|
-ljava \
|
||||||
-framework Accelerate \
|
-framework Accelerate \
|
||||||
-framework ApplicationServices \
|
-framework ApplicationServices \
|
||||||
-framework AudioToolbox \
|
-framework AudioToolbox \
|
||||||
@ -107,6 +108,8 @@ ifeq ($(call isTargetOs, macosx), true)
|
|||||||
-framework QuartzCore, \
|
-framework QuartzCore, \
|
||||||
))
|
))
|
||||||
|
|
||||||
|
$(BUILD_LIBOSXAPP): $(call FindLib, java.base, java)
|
||||||
|
|
||||||
TARGETS += $(BUILD_LIBOSXAPP)
|
TARGETS += $(BUILD_LIBOSXAPP)
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
@ -1286,6 +1286,7 @@ static jclass jc_CInputMethod = NULL;
|
|||||||
|
|
||||||
array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_firstRectForCharacterRange,
|
array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_firstRectForCharacterRange,
|
||||||
theRange.location); // AWT_THREADING Safe (AWTRunLoopMode)
|
theRange.location); // AWT_THREADING Safe (AWTRunLoopMode)
|
||||||
|
CHECK_EXCEPTION();
|
||||||
|
|
||||||
_array = (*env)->GetIntArrayElements(env, array, &isCopy);
|
_array = (*env)->GetIntArrayElements(env, array, &isCopy);
|
||||||
if (_array) {
|
if (_array) {
|
||||||
|
@ -56,7 +56,7 @@ static jmethodID sjm_printerJob = NULL;
|
|||||||
GET_CPRINTERJOB_CLASS_RETURN(ret); \
|
GET_CPRINTERJOB_CLASS_RETURN(ret); \
|
||||||
GET_METHOD_RETURN(sjm_getNSPrintInfo, sjc_CPrinterJob, "getNSPrintInfo", "()J", 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_CPRINTERDIALOG_CLASS_RETURN(ret); \
|
||||||
GET_FIELD_RETURN(sjm_printerJob, sjc_CPrinterDialog, "fPrinterJob", "Lsun/lwawt/macosx/CPrinterJob;", ret);
|
GET_FIELD_RETURN(sjm_printerJob, sjc_CPrinterDialog, "fPrinterJob", "Lsun/lwawt/macosx/CPrinterJob;", ret);
|
||||||
|
|
||||||
@ -651,6 +651,7 @@ JNF_COCOA_ENTER(env);
|
|||||||
|
|
||||||
// <rdar://problem/4367998> JTable.print attributes are ignored
|
// <rdar://problem/4367998> JTable.print attributes are ignored
|
||||||
jobject pageable = (*env)->CallObjectMethod(env, jthis, jm_getPageable); // AWT_THREADING Safe (!appKit)
|
jobject pageable = (*env)->CallObjectMethod(env, jthis, jm_getPageable); // AWT_THREADING Safe (!appKit)
|
||||||
|
CHECK_EXCEPTION();
|
||||||
javaPrinterJobToNSPrintInfo(env, jthis, pageable, printInfo);
|
javaPrinterJobToNSPrintInfo(env, jthis, pageable, printInfo);
|
||||||
|
|
||||||
PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
|
PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
|
||||||
@ -691,11 +692,12 @@ JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterPageDialog_showDialog
|
|||||||
|
|
||||||
jboolean result = JNI_FALSE;
|
jboolean result = JNI_FALSE;
|
||||||
JNF_COCOA_ENTER(env);
|
JNF_COCOA_ENTER(env);
|
||||||
GET_CPRINTERDIALOG_METHOD_RETURN(NO);
|
GET_CPRINTERDIALOG_FIELD_RETURN(NO);
|
||||||
GET_NSPRINTINFO_METHOD_RETURN(NO)
|
GET_NSPRINTINFO_METHOD_RETURN(NO)
|
||||||
jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob);
|
jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob);
|
||||||
if (printerJob == NULL) return NO;
|
if (printerJob == NULL) return NO;
|
||||||
NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
|
NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
|
||||||
|
CHECK_EXCEPTION();
|
||||||
if (printInfo == NULL) return result;
|
if (printInfo == NULL) return result;
|
||||||
|
|
||||||
jobject page = (*env)->GetObjectField(env, jthis, jm_page);
|
jobject page = (*env)->GetObjectField(env, jthis, jm_page);
|
||||||
@ -740,7 +742,7 @@ JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJobDialog_showDialog
|
|||||||
|
|
||||||
jboolean result = JNI_FALSE;
|
jboolean result = JNI_FALSE;
|
||||||
JNF_COCOA_ENTER(env);
|
JNF_COCOA_ENTER(env);
|
||||||
GET_CPRINTERDIALOG_METHOD_RETURN(NO);
|
GET_CPRINTERDIALOG_FIELD_RETURN(NO);
|
||||||
jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob);
|
jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob);
|
||||||
if (printerJob == NULL) return NO;
|
if (printerJob == NULL) return NO;
|
||||||
GET_NSPRINTINFO_METHOD_RETURN(NO)
|
GET_NSPRINTINFO_METHOD_RETURN(NO)
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import "GeomUtilities.h"
|
#import "GeomUtilities.h"
|
||||||
|
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||||
|
|
||||||
static jobject NewJavaRect(JNIEnv *env, jdouble x, jdouble y, jdouble w, jdouble 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);
|
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_getY, sjc_Rectangle2D, "getY", "()D", NSZeroRect);
|
||||||
DECLARE_METHOD_RETURN(jm_rect_getWidth, sjc_Rectangle2D, "getWidth", "()D", NSZeroRect);
|
DECLARE_METHOD_RETURN(jm_rect_getWidth, sjc_Rectangle2D, "getWidth", "()D", NSZeroRect);
|
||||||
DECLARE_METHOD_RETURN(jm_rect_getHeight, sjc_Rectangle2D, "getHeight", "()D", NSZeroRect);
|
DECLARE_METHOD_RETURN(jm_rect_getHeight, sjc_Rectangle2D, "getHeight", "()D", NSZeroRect);
|
||||||
return NSMakeRect((*env)->CallDoubleMethod(env, rect, jm_rect_getX),
|
jdouble x = (*env)->CallDoubleMethod(env, rect, jm_rect_getX); CHECK_EXCEPTION();
|
||||||
(*env)->CallDoubleMethod(env, rect, jm_rect_getY),
|
jdouble y = (*env)->CallDoubleMethod(env, rect, jm_rect_getY); CHECK_EXCEPTION();
|
||||||
(*env)->CallDoubleMethod(env, rect, jm_rect_getWidth),
|
jdouble w = (*env)->CallDoubleMethod(env, rect, jm_rect_getWidth); CHECK_EXCEPTION();
|
||||||
(*env)->CallDoubleMethod(env, rect, jm_rect_getHeight));
|
jdouble h = (*env)->CallDoubleMethod(env, rect, jm_rect_getHeight); CHECK_EXCEPTION();
|
||||||
|
return NSMakeRect(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject NSToJavaPoint(JNIEnv *env, NSPoint point) {
|
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_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_getX, sjc_Point2D, "getX", "()D", NSZeroPoint);
|
||||||
DECLARE_METHOD_RETURN(jm_pt_getY, sjc_Point2D, "getY", "()D", NSZeroPoint);
|
DECLARE_METHOD_RETURN(jm_pt_getY, sjc_Point2D, "getY", "()D", NSZeroPoint);
|
||||||
|
jdouble x = (*env)->CallDoubleMethod(env, point, jm_pt_getX); CHECK_EXCEPTION();
|
||||||
return NSMakePoint((*env)->CallDoubleMethod(env, point, jm_pt_getX),
|
jdouble y = (*env)->CallDoubleMethod(env, point, jm_pt_getY); CHECK_EXCEPTION();
|
||||||
(*env)->CallDoubleMethod(env, point, jm_pt_getY));
|
return NSMakePoint(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject NSToJavaSize(JNIEnv *env, NSSize size) {
|
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_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_getWidth, sjc_Dimension2D, "getWidth", "()D", NSZeroSize);
|
||||||
DECLARE_METHOD_RETURN(jm_sz_getHeight, sjc_Dimension2D, "getHeight", "()D", NSZeroSize);
|
DECLARE_METHOD_RETURN(jm_sz_getHeight, sjc_Dimension2D, "getHeight", "()D", NSZeroSize);
|
||||||
|
jdouble w = (*env)->CallDoubleMethod(env, dimension, jm_sz_getWidth); CHECK_EXCEPTION();
|
||||||
return NSMakeSize((*env)->CallDoubleMethod(env, dimension, jm_sz_getWidth),
|
jdouble h = (*env)->CallDoubleMethod(env, dimension, jm_sz_getHeight); CHECK_EXCEPTION();
|
||||||
(*env)->CallDoubleMethod(env, dimension, jm_sz_getHeight));
|
return NSMakeSize(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSScreen *primaryScreen(JNIEnv *env) {
|
static NSScreen *primaryScreen(JNIEnv *env) {
|
||||||
NSScreen *primaryScreen = [[NSScreen screens] objectAtIndex:0];
|
NSScreen *primaryScreen = [[NSScreen screens] objectAtIndex:0];
|
||||||
if (primaryScreen != nil) return primaryScreen;
|
if (primaryScreen != nil) return primaryScreen;
|
||||||
|
if (env != NULL) [JNFException raise:env as:kRuntimeException reason:"Failed to convert, no screen."];
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,6 +640,7 @@ static NSObject *sAttributeNamesLOCK = nil;
|
|||||||
} else {
|
} else {
|
||||||
AWTView *view = fView;
|
AWTView *view = fView;
|
||||||
jobject jax = (*env)->CallStaticObjectMethod(env, sjc_CAccessible, sjm_getSwingAccessible, fAccessible);
|
jobject jax = (*env)->CallStaticObjectMethod(env, sjc_CAccessible, sjm_getSwingAccessible, fAccessible);
|
||||||
|
CHECK_EXCEPTION();
|
||||||
|
|
||||||
if ((*env)->IsInstanceOf(env, jax, sjc_Window)) {
|
if ((*env)->IsInstanceOf(env, jax, sjc_Window)) {
|
||||||
// In this case jparent is an owner toplevel and we should retrieve its own view
|
// In this case jparent is an owner toplevel and we should retrieve its own view
|
||||||
@ -928,6 +929,7 @@ static NSObject *sAttributeNamesLOCK = nil;
|
|||||||
if ([(NSNumber*)value boolValue])
|
if ([(NSNumber*)value boolValue])
|
||||||
{
|
{
|
||||||
(*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestFocus, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
|
(*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestFocus, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
|
||||||
|
CHECK_EXCEPTION();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +160,6 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) {
|
|||||||
|
|
||||||
DECLARE_STATIC_METHOD_RETURN(jm_getTextRange, sjc_CAccessibleText, "getTextRange",
|
DECLARE_STATIC_METHOD_RETURN(jm_getTextRange, sjc_CAccessibleText, "getTextRange",
|
||||||
"(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;", nil);
|
"(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;", nil);
|
||||||
CHECK_EXCEPTION();
|
|
||||||
jobject jrange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getTextRange,
|
jobject jrange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getTextRange,
|
||||||
axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent);
|
axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent);
|
||||||
CHECK_EXCEPTION();
|
CHECK_EXCEPTION();
|
||||||
|
@ -123,6 +123,7 @@ static jclass sjc_CPrinterJob = NULL;
|
|||||||
DECLARE_METHOD_RETURN(jm_getJobName, sjc_CPrinterJob, "getJobName", "()Ljava/lang/String;", nil);
|
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)
|
jobject o = (*env)->CallObjectMethod(env, fPrinterJob, jm_getJobName); // AWT_THREADING Safe (known object)
|
||||||
|
CHECK_EXCEPTION();
|
||||||
id result = JNFJavaToNSString(env, o);
|
id result = JNFJavaToNSString(env, o);
|
||||||
(*env)->DeleteLocalRef(env, o);
|
(*env)->DeleteLocalRef(env, o);
|
||||||
return result;
|
return result;
|
||||||
|
@ -29,11 +29,24 @@
|
|||||||
#include "jni.h"
|
#include "jni.h"
|
||||||
#include "jni_util.h"
|
#include "jni_util.h"
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
/******** LOGGING SUPPORT *********/
|
/******** LOGGING SUPPORT *********/
|
||||||
|
|
||||||
#define LOG_NULL(dst_var, name) \
|
#define LOG_NULL(dst_var, name) \
|
||||||
if (dst_var == NULL) { \
|
if (dst_var == NULL) { \
|
||||||
NSLog(@"Bad JNI lookup %s\n", name); \
|
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 *********/
|
/******** GET CLASS SUPPORT *********/
|
||||||
@ -147,9 +160,44 @@
|
|||||||
|
|
||||||
/********* EXCEPTION_HANDLING *********/
|
/********* 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() \
|
#define CHECK_EXCEPTION() \
|
||||||
if ((*env)->ExceptionOccurred(env) != NULL) { \
|
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) \
|
#define CHECK_EXCEPTION_NULL_RETURN(x, y) \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user