Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.
/jdk13u-devPublic archive

Commit cdb993e

Browse files
author
Vladimir Kempik
committed
8259343: [macOS] Update JNI error handling in Cocoa code.
Reviewed-by: yan Backport-of: d6a2105
1 parent ad45c98 commit cdb993e

File tree

8 files changed

+74
-15
lines changed

8 files changed

+74
-15
lines changed

make/lib/Lib-java.desktop.gmk

+3
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ ifeq ($(call isTargetOs, macosx), true)
9898
LDFLAGS := $(LDFLAGS_JDKLIB) \
9999
$(call SET_SHARED_LIBRARY_ORIGIN), \
100100
LIBS := \
101+
-ljava \
101102
-framework Accelerate \
102103
-framework ApplicationServices \
103104
-framework AudioToolbox \
@@ -112,6 +113,8 @@ ifeq ($(call isTargetOs, macosx), true)
112113
-framework QuartzCore, \
113114
))
114115

116+
$(BUILD_LIBOSXAPP): $(call FindLib, java.base, java)
117+
115118
TARGETS += $(BUILD_LIBOSXAPP)
116119

117120
##############################################################################

src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m

+1
Original file line numberDiff line numberDiff line change
@@ -1290,6 +1290,7 @@ - (NSRect) firstRectForCharacterRange:(NSRange)theRange actualRange:(NSRangePoin
12901290

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

12941295
_array = (*env)->GetIntArrayElements(env, array, &isCopy);
12951296
if (_array) {

src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m

+5-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
GET_CPRINTERJOB_CLASS_RETURN(ret); \
5757
GET_METHOD_RETURN(sjm_getNSPrintInfo, sjc_CPrinterJob, "getNSPrintInfo", "()J", ret);
5858

59-
#defineGET_CPRINTERDIALOG_METHOD_RETURN(ret) \
59+
#defineGET_CPRINTERDIALOG_FIELD_RETURN(ret) \
6060
GET_CPRINTERDIALOG_CLASS_RETURN(ret); \
6161
GET_METHOD_RETURN(sjm_printerJob, sjc_CPrinterDialog, "fPrinterJob", "Lsun/lwawt/macosx/CPrinterJob;", ret);
6262

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

625625
// <rdar://problem/4367998> JTable.print attributes are ignored
626626
jobject pageable = (*env)->CallObjectMethod(env, jthis, jm_getPageable); // AWT_THREADING Safe (!appKit)
627+
CHECK_EXCEPTION();
627628
javaPrinterJobToNSPrintInfo(env, jthis, pageable, printInfo);
628629

629630
PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
@@ -664,11 +665,12 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj
664665

665666
jboolean result = JNI_FALSE;
666667
JNF_COCOA_ENTER(env);
667-
GET_CPRINTERDIALOG_METHOD_RETURN(NO);
668+
GET_CPRINTERDIALOG_FIELD_RETURN(NO);
668669
GET_NSPRINTINFO_METHOD_RETURN(NO)
669670
jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob);
670671
if (printerJob == NULL) returnNO;
671672
NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
673+
CHECK_EXCEPTION();
672674
if (printInfo == NULL) return result;
673675

674676
jobject page = (*env)->GetObjectField(env, jthis, jm_page);
@@ -713,7 +715,7 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj
713715

714716
jboolean result = JNI_FALSE;
715717
JNF_COCOA_ENTER(env);
716-
GET_CPRINTERDIALOG_METHOD_RETURN(NO);
718+
GET_CPRINTERDIALOG_FIELD_RETURN(NO);
717719
jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob);
718720
if (printerJob == NULL) returnNO;
719721
GET_NSPRINTINFO_METHOD_RETURN(NO)

src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m

+13-10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525

2626
#import"GeomUtilities.h"
27+
#import<JavaNativeFoundation/JavaNativeFoundation.h>
2728

2829
static jobject NewJavaRect(JNIEnv *env, jdouble x, jdouble y, jdouble w, jdouble h) {
2930
DECLARE_CLASS_RETURN(sjc_Rectangle2DDouble, "java/awt/geom/Rectangle2D$Double", NULL);
@@ -55,10 +56,11 @@ NSRect JavaToNSRect(JNIEnv *env, jobject rect) {
5556
DECLARE_METHOD_RETURN(jm_rect_getY, sjc_Rectangle2D, "getY", "()D", NSZeroRect);
5657
DECLARE_METHOD_RETURN(jm_rect_getWidth, sjc_Rectangle2D, "getWidth", "()D", NSZeroRect);
5758
DECLARE_METHOD_RETURN(jm_rect_getHeight, sjc_Rectangle2D, "getHeight", "()D", NSZeroRect);
58-
returnNSMakeRect((*env)->CallDoubleMethod(env, rect, jm_rect_getX),
59-
(*env)->CallDoubleMethod(env, rect, jm_rect_getY),
60-
(*env)->CallDoubleMethod(env, rect, jm_rect_getWidth),
61-
(*env)->CallDoubleMethod(env, rect, jm_rect_getHeight));
59+
jdouble x = (*env)->CallDoubleMethod(env, rect, jm_rect_getX); CHECK_EXCEPTION();
60+
jdouble y = (*env)->CallDoubleMethod(env, rect, jm_rect_getY); CHECK_EXCEPTION();
61+
jdouble w = (*env)->CallDoubleMethod(env, rect, jm_rect_getWidth); CHECK_EXCEPTION();
62+
jdouble h = (*env)->CallDoubleMethod(env, rect, jm_rect_getHeight); CHECK_EXCEPTION();
63+
returnNSMakeRect(x, y, w, h);
6264
}
6365

6466
jobject NSToJavaPoint(JNIEnv *env, NSPoint point) {
@@ -73,9 +75,9 @@ NSPoint JavaToNSPoint(JNIEnv *env, jobject point) {
7375
DECLARE_CLASS_RETURN(sjc_Point2D, "java/awt/geom/Point2D", NSZeroPoint);
7476
DECLARE_METHOD_RETURN(jm_pt_getX, sjc_Point2D, "getX", "()D", NSZeroPoint);
7577
DECLARE_METHOD_RETURN(jm_pt_getY, sjc_Point2D, "getY", "()D", NSZeroPoint);
76-
77-
returnNSMakePoint((*env)->CallDoubleMethod(env, point, jm_pt_getX),
78-
(*env)->CallDoubleMethod(env, point, jm_pt_getY));
78+
jdouble x = (*env)->CallDoubleMethod(env, point, jm_pt_getX); CHECK_EXCEPTION();
79+
jdouble y = (*env)->CallDoubleMethod(env, point, jm_pt_getY); CHECK_EXCEPTION();
80+
returnNSMakePoint(x, y);
7981
}
8082

8183
jobject NSToJavaSize(JNIEnv *env, NSSize size) {
@@ -90,14 +92,15 @@ NSSize JavaToNSSize(JNIEnv *env, jobject dimension) {
9092
DECLARE_CLASS_RETURN(sjc_Dimension2D, "java/awt/geom/Dimension2D", NSZeroSize);
9193
DECLARE_METHOD_RETURN(jm_sz_getWidth, sjc_Dimension2D, "getWidth", "()D", NSZeroSize);
9294
DECLARE_METHOD_RETURN(jm_sz_getHeight, sjc_Dimension2D, "getHeight", "()D", NSZeroSize);
93-
94-
returnNSMakeSize((*env)->CallDoubleMethod(env, dimension, jm_sz_getWidth),
95-
(*env)->CallDoubleMethod(env, dimension, jm_sz_getHeight));
95+
jdouble w = (*env)->CallDoubleMethod(env, dimension, jm_sz_getWidth); CHECK_EXCEPTION();
96+
jdouble h = (*env)->CallDoubleMethod(env, dimension, jm_sz_getHeight); CHECK_EXCEPTION();
97+
returnNSMakeSize(w, h);
9698
}
9799

98100
staticNSScreen *primaryScreen(JNIEnv *env) {
99101
NSScreen *primaryScreen = [[NSScreenscreens] objectAtIndex:0];
100102
if (primaryScreen != nil) return primaryScreen;
103+
if (env != NULL) [JNFException raise:env as:kRuntimeExceptionreason:"Failed to convert, no screen."];
101104
returnnil;
102105
}
103106

src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m

+2
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ - (id)parent
623623
} else {
624624
AWTView *view = fView;
625625
jobject jax = (*env)->CallStaticObjectMethod(env, sjc_CAccessible, sjm_getSwingAccessible, fAccessible);
626+
CHECK_EXCEPTION();
626627

627628
if ((*env)->IsInstanceOf(env, jax, sjc_Window)) {
628629
// In this case jparent is an owner toplevel and we should retrieve its own view
@@ -911,6 +912,7 @@ - (void)accessibilitySetFocusedAttribute:(id)value
911912
if ([(NSNumber*)value boolValue])
912913
{
913914
(*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestFocus, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
915+
CHECK_EXCEPTION();
914916
}
915917
}
916918

src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m

-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ - (NSString *)accessibilityValueAttribute
160160

161161
DECLARE_STATIC_METHOD_RETURN(jm_getTextRange, sjc_CAccessibleText, "getTextRange",
162162
"(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;", nil);
163-
CHECK_EXCEPTION();
164163
jobject jrange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getTextRange,
165164
axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent);
166165
CHECK_EXCEPTION();

src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterView.m

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ - (NSString*)printJobTitle
123123
DECLARE_METHOD_RETURN(jm_getJobName, sjc_CPrinterJob, "getJobName", "()Ljava/lang/String;", nil);
124124

125125
jobject o = (*env)->CallObjectMethod(env, fPrinterJob, jm_getJobName); // AWT_THREADING Safe (known object)
126+
CHECK_EXCEPTION();
126127
id result = JNFJavaToNSString(env, o);
127128
(*env)->DeleteLocalRef(env, o);
128129
return result;

src/java.desktop/macosx/native/libosxapp/JNIUtilities.h

+49-1
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,24 @@
2929
#include"jni.h"
3030
#include"jni_util.h"
3131

32+
#import<Cocoa/Cocoa.h>
33+
3234
/******** LOGGING SUPPORT *********/
3335

3436
#defineLOG_NULL(dst_var, name) \
3537
if (dst_var == NULL) { \
3638
NSLog(@"Bad JNI lookup %s\n", name); \
39+
NSLog(@"%@",[NSThreadcallStackSymbols]); \
40+
if ([NSThreadisMainThread] == NO) { \
41+
if ((*env)->ExceptionOccurred(env) == NULL) { \
42+
JNU_ThrowInternalError(env, "Bad JNI Lookup"); \
43+
} \
44+
} else { \
45+
if ((*env)->ExceptionOccurred(env) != NULL) { \
46+
(*env)->ExceptionDescribe(env); \
47+
} \
48+
} \
49+
[NSExceptionraise:NSGenericExceptionformat:@"JNI Lookup Exception"]; \
3750
}
3851

3952
/******** GET CLASS SUPPORT *********/
@@ -147,9 +160,44 @@
147160

148161
/********* EXCEPTION_HANDLING *********/
149162

163+
/*
164+
* Some explanation to set context of the bigger picture.
165+
* Before returning to Java from JNI, NSExceptions are caught - so long as
166+
* the body of the native method is wrapped in the ENTER/EXIT macros.
167+
* So if we want to directly return to Java from some nested Objective-C
168+
* function when detecting a Java exception, we just need to raise an
169+
* NSException. Then clear that right before returning to Java,
170+
* leaving the Java exception to be seen back in Java-land.
171+
*
172+
* But if the current thread is the Appkit thread we might as well clear
173+
* the Java Exception right now since there's nothing to receive it.
174+
* In such a case control will propagate back to the run loop which might
175+
* terminate the application. One drawback of that is that the location of
176+
* termination does not show where the NSException originated.
177+
* And for whatever reason, something swallows that exception.
178+
* So as a debugging aid, when on the AppKit thread we can provide a
179+
* way (via an env. var.) to log the location.
180+
* Additionally provide a similar way to prevent the NSException being
181+
* raised and instead just clear the Java Exception.
182+
* Together these provide alternate behaviours for more debugging info
183+
* or maybe a way for the app to continue running depending on the exact
184+
* nature of the problem that has been detected and how survivable it is.
185+
*/
150186
#defineCHECK_EXCEPTION() \
151187
if ((*env)->ExceptionOccurred(env) != NULL) { \
152-
(*env)->ExceptionClear(env); \
188+
if ([NSThreadisMainThread] == YES) { \
189+
if (getenv("JNU_APPKIT_TRACE")) { \
190+
(*env)->ExceptionDescribe(env); \
191+
NSLog(@"%@",[NSThreadcallStackSymbols]); \
192+
} else { \
193+
(*env)->ExceptionClear(env); \
194+
} \
195+
} \
196+
if (getenv("JNU_NO_COCOA_EXCEPTION") == NULL) { \
197+
[NSExceptionraise:NSGenericExceptionformat:@"Java Exception"]; \
198+
} else { \
199+
(*env)->ExceptionClear(env); \
200+
} \
153201
};
154202

155203
#defineCHECK_EXCEPTION_NULL_RETURN(x, y) \

0 commit comments

Comments
 (0)
close