Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h
41152 views
1
/*
2
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#ifndef __JNIUTILITIES_H
27
#define __JNIUTILITIES_H
28
29
#include "jni.h"
30
#include "jni_util.h"
31
32
#import <Cocoa/Cocoa.h>
33
34
/******** LOGGING SUPPORT *********/
35
36
#define LOG_NULL(dst_var, name) \
37
if (dst_var == NULL) { \
38
NSLog(@"Bad JNI lookup %s\n", name); \
39
NSLog(@"%@",[NSThread callStackSymbols]); \
40
if ([NSThread isMainThread] == 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
[NSException raise:NSGenericException format:@"JNI Lookup Exception"]; \
50
}
51
52
/******** GET CLASS SUPPORT *********/
53
54
#define GET_CLASS(dst_var, cls) \
55
if (dst_var == NULL) { \
56
dst_var = (*env)->FindClass(env, cls); \
57
if (dst_var != NULL) dst_var = (*env)->NewGlobalRef(env, dst_var); \
58
} \
59
LOG_NULL(dst_var, cls); \
60
CHECK_NULL(dst_var);
61
62
#define DECLARE_CLASS(dst_var, cls) \
63
static jclass dst_var = NULL; \
64
GET_CLASS(dst_var, cls);
65
66
#define GET_CLASS_RETURN(dst_var, cls, ret) \
67
if (dst_var == NULL) { \
68
dst_var = (*env)->FindClass(env, cls); \
69
if (dst_var != NULL) dst_var = (*env)->NewGlobalRef(env, dst_var); \
70
} \
71
LOG_NULL(dst_var, cls); \
72
CHECK_NULL_RETURN(dst_var, ret);
73
74
#define DECLARE_CLASS_RETURN(dst_var, cls, ret) \
75
static jclass dst_var = NULL; \
76
GET_CLASS_RETURN(dst_var, cls, ret);
77
78
79
/******** GET METHOD SUPPORT *********/
80
81
#define GET_METHOD(dst_var, cls, name, signature) \
82
if (dst_var == NULL) { \
83
dst_var = (*env)->GetMethodID(env, cls, name, signature); \
84
} \
85
LOG_NULL(dst_var, name); \
86
CHECK_NULL(dst_var);
87
88
#define DECLARE_METHOD(dst_var, cls, name, signature) \
89
static jmethodID dst_var = NULL; \
90
GET_METHOD(dst_var, cls, name, signature);
91
92
#define GET_METHOD_RETURN(dst_var, cls, name, signature, ret) \
93
if (dst_var == NULL) { \
94
dst_var = (*env)->GetMethodID(env, cls, name, signature); \
95
} \
96
LOG_NULL(dst_var, name); \
97
CHECK_NULL_RETURN(dst_var, ret);
98
99
#define DECLARE_METHOD_RETURN(dst_var, cls, name, signature, ret) \
100
static jmethodID dst_var = NULL; \
101
GET_METHOD_RETURN(dst_var, cls, name, signature, ret);
102
103
#define GET_STATIC_METHOD(dst_var, cls, name, signature) \
104
if (dst_var == NULL) { \
105
dst_var = (*env)->GetStaticMethodID(env, cls, name, signature); \
106
} \
107
LOG_NULL(dst_var, name); \
108
CHECK_NULL(dst_var);
109
110
#define DECLARE_STATIC_METHOD(dst_var, cls, name, signature) \
111
static jmethodID dst_var = NULL; \
112
GET_STATIC_METHOD(dst_var, cls, name, signature);
113
114
#define GET_STATIC_METHOD_RETURN(dst_var, cls, name, signature, ret) \
115
if (dst_var == NULL) { \
116
dst_var = (*env)->GetStaticMethodID(env, cls, name, signature); \
117
} \
118
LOG_NULL(dst_var, name); \
119
CHECK_NULL_RETURN(dst_var, ret);
120
121
#define DECLARE_STATIC_METHOD_RETURN(dst_var, cls, name, signature, ret) \
122
static jmethodID dst_var = NULL; \
123
GET_STATIC_METHOD_RETURN(dst_var, cls, name, signature, ret);
124
125
/******** GET FIELD SUPPORT *********/
126
127
128
#define GET_FIELD(dst_var, cls, name, signature) \
129
if (dst_var == NULL) { \
130
dst_var = (*env)->GetFieldID(env, cls, name, signature); \
131
} \
132
LOG_NULL(dst_var, name); \
133
CHECK_NULL(dst_var);
134
135
#define DECLARE_FIELD(dst_var, cls, name, signature) \
136
static jfieldID dst_var = NULL; \
137
GET_FIELD(dst_var, cls, name, signature);
138
139
#define GET_FIELD_RETURN(dst_var, cls, name, signature, ret) \
140
if (dst_var == NULL) { \
141
dst_var = (*env)->GetFieldID(env, cls, name, signature); \
142
} \
143
LOG_NULL(dst_var, name); \
144
CHECK_NULL_RETURN(dst_var, ret);
145
146
#define DECLARE_FIELD_RETURN(dst_var, cls, name, signature, ret) \
147
static jfieldID dst_var = NULL; \
148
GET_FIELD_RETURN(dst_var, cls, name, signature, ret);
149
150
#define GET_STATIC_FIELD_RETURN(dst_var, cls, name, signature, ret) \
151
if (dst_var == NULL) { \
152
dst_var = (*env)->GetStaticFieldID(env, cls, name, signature); \
153
} \
154
LOG_NULL(dst_var, name); \
155
CHECK_NULL_RETURN(dst_var, ret);
156
157
#define DECLARE_STATIC_FIELD_RETURN(dst_var, cls, name, signature, ret) \
158
static jfieldID dst_var = NULL; \
159
GET_STATIC_FIELD_RETURN(dst_var, cls, name, signature, ret);
160
161
/********* EXCEPTION_HANDLING *********/
162
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
*/
186
#define CHECK_EXCEPTION() \
187
if ((*env)->ExceptionOccurred(env) != NULL) { \
188
if ([NSThread isMainThread] == YES) { \
189
if (getenv("JNU_APPKIT_TRACE")) { \
190
(*env)->ExceptionDescribe(env); \
191
NSLog(@"%@",[NSThread callStackSymbols]); \
192
} else { \
193
(*env)->ExceptionClear(env); \
194
} \
195
} \
196
if (getenv("JNU_NO_COCOA_EXCEPTION") == NULL) { \
197
[NSException raise:NSGenericException format:@"Java Exception"]; \
198
} else { \
199
(*env)->ExceptionClear(env); \
200
} \
201
};
202
203
#define CHECK_EXCEPTION_NULL_RETURN(x, y) \
204
CHECK_EXCEPTION(); \
205
if ((x) == NULL) { \
206
return y; \
207
};
208
209
/* Create a pool and initiate a try block to catch any exception */
210
#define JNI_COCOA_ENTER(env) \
211
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \
212
@try {
213
214
/* Don't allow NSExceptions to escape to Java.
215
* If there is a Java exception that has been thrown that should escape.
216
* And ensure we drain the auto-release pool.
217
*/
218
#define JNI_COCOA_EXIT(env) \
219
} \
220
@catch (NSException *e) { \
221
NSLog(@"%@", [e callStackSymbols]); \
222
} \
223
@finally { \
224
[pool drain]; \
225
};
226
227
/* Same as above but adds a clean up action.
228
* Requires that whatever is being cleaned up is in scope.
229
*/
230
#define JNI_COCOA_EXIT_WITH_ACTION(env, action) \
231
} \
232
@catch (NSException *e) { \
233
{ action; }; \
234
NSLog(@"%@", [e callStackSymbols]); \
235
} \
236
@finally { \
237
[pool drain]; \
238
};
239
240
/******** STRING CONVERSION SUPPORT *********/
241
242
JNIEXPORT NSString* JavaStringToNSString(JNIEnv *env, jstring jstr);
243
244
JNIEXPORT jstring NSStringToJavaString(JNIEnv* env, NSString *str);
245
246
JNIEXPORT NSString* NormalizedPathNSStringFromJavaString(JNIEnv *env, jstring pathStr);
247
248
JNIEXPORT jstring NormalizedPathJavaStringFromNSString(JNIEnv* env, NSString *str);
249
250
#endif /* __JNIUTILITIES_H */
251
252