1 /*
2  * Copyright (c) 1997, 2010, 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 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 
30 #include "jvm.h"
31 #include "jni.h"
32 #include "jni_util.h"
33 
34 /* Due to a bug in the win32 C runtime library strings
35  * such as "z:" need to be appended with a "." so we
36  * must allocate at least 4 bytes to allow room for
37  * this expansion. See 4235353 for details.
38  */
39 #define MALLOC_MIN4(len) ((char *)malloc((len) + 1 < 4 ? 4 : (len) + 1))
40 
41 /**
42  * Throw a Java exception by name. Similar to SignalError.
43  */
44 JNIEXPORT void JNICALL
JNU_ThrowByName(JNIEnv * env,const char * name,const char * msg)45 JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg)
46 {
47     jclass cls = (*env)->FindClass(env, name);
48 
49     if (cls != 0) /* Otherwise an exception has already been thrown */
50         (*env)->ThrowNew(env, cls, msg);
51 }
52 
53 /* JNU_Throw common exceptions */
54 
55 JNIEXPORT void JNICALL
JNU_ThrowNullPointerException(JNIEnv * env,const char * msg)56 JNU_ThrowNullPointerException(JNIEnv *env, const char *msg)
57 {
58     JNU_ThrowByName(env, "java/lang/NullPointerException", msg);
59 }
60 
61 JNIEXPORT void JNICALL
JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv * env,const char * msg)62 JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg)
63 {
64     JNU_ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", msg);
65 }
66 
67 JNIEXPORT void JNICALL
JNU_ThrowOutOfMemoryError(JNIEnv * env,const char * msg)68 JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg)
69 {
70     JNU_ThrowByName(env, "java/lang/OutOfMemoryError", msg);
71 }
72 
73 JNIEXPORT void JNICALL
JNU_ThrowIllegalArgumentException(JNIEnv * env,const char * msg)74 JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg)
75 {
76     JNU_ThrowByName(env, "java/lang/IllegalArgumentException", msg);
77 }
78 
79 JNIEXPORT void JNICALL
JNU_ThrowIllegalAccessError(JNIEnv * env,const char * msg)80 JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg)
81 {
82     JNU_ThrowByName(env, "java/lang/IllegalAccessError", msg);
83 }
84 
85 JNIEXPORT void JNICALL
JNU_ThrowIllegalAccessException(JNIEnv * env,const char * msg)86 JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg)
87 {
88     JNU_ThrowByName(env, "java/lang/IllegalAccessException", msg);
89 }
90 
91 JNIEXPORT void JNICALL
JNU_ThrowInternalError(JNIEnv * env,const char * msg)92 JNU_ThrowInternalError(JNIEnv *env, const char *msg)
93 {
94     JNU_ThrowByName(env, "java/lang/InternalError", msg);
95 }
96 
97 JNIEXPORT void JNICALL
JNU_ThrowNoSuchFieldException(JNIEnv * env,const char * msg)98 JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg)
99 {
100     JNU_ThrowByName(env, "java/lang/NoSuchFieldException", msg);
101 }
102 
103 JNIEXPORT void JNICALL
JNU_ThrowNoSuchMethodException(JNIEnv * env,const char * msg)104 JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg)
105 {
106     JNU_ThrowByName(env, "java/lang/NoSuchMethodException", msg);
107 }
108 
109 JNIEXPORT void JNICALL
JNU_ThrowClassNotFoundException(JNIEnv * env,const char * msg)110 JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg)
111 {
112     JNU_ThrowByName(env, "java/lang/ClassNotFoundException", msg);
113 }
114 
115 JNIEXPORT void JNICALL
JNU_ThrowNumberFormatException(JNIEnv * env,const char * msg)116 JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg)
117 {
118     JNU_ThrowByName(env, "java/lang/NumberFormatException", msg);
119 }
120 
121 JNIEXPORT void JNICALL
JNU_ThrowIOException(JNIEnv * env,const char * msg)122 JNU_ThrowIOException(JNIEnv *env, const char *msg)
123 {
124     JNU_ThrowByName(env, "java/io/IOException", msg);
125 }
126 
127 JNIEXPORT void JNICALL
JNU_ThrowNoSuchFieldError(JNIEnv * env,const char * msg)128 JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg)
129 {
130     JNU_ThrowByName(env, "java/lang/NoSuchFieldError", msg);
131 }
132 
133 JNIEXPORT void JNICALL
JNU_ThrowNoSuchMethodError(JNIEnv * env,const char * msg)134 JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg)
135 {
136     JNU_ThrowByName(env, "java/lang/NoSuchMethodError", msg);
137 }
138 
139 JNIEXPORT void JNICALL
JNU_ThrowStringIndexOutOfBoundsException(JNIEnv * env,const char * msg)140 JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg)
141 {
142     JNU_ThrowByName(env, "java/lang/StringIndexOutOfBoundsException", msg);
143 }
144 
145 JNIEXPORT void JNICALL
JNU_ThrowInstantiationException(JNIEnv * env,const char * msg)146 JNU_ThrowInstantiationException(JNIEnv *env, const char *msg)
147 {
148     JNU_ThrowByName(env, "java/lang/InstantiationException", msg);
149 }
150 
151 
152 /* Throw an exception by name, using the string returned by
153  * JVM_LastErrorString for the detail string.  If the last-error
154  * string is NULL, use the given default detail string.
155  */
156 JNIEXPORT void JNICALL
JNU_ThrowByNameWithLastError(JNIEnv * env,const char * name,const char * defaultDetail)157 JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
158                              const char *defaultDetail)
159 {
160     char buf[256];
161     int n = JVM_GetLastErrorString(buf, sizeof(buf));
162 
163     if (n > 0) {
164         jstring s = JNU_NewStringPlatform(env, buf);
165         if (s != NULL) {
166             jobject x = JNU_NewObjectByName(env, name,
167                                             "(Ljava/lang/String;)V", s);
168             if (x != NULL) {
169                 (*env)->Throw(env, x);
170             }
171         }
172     }
173     if (!(*env)->ExceptionOccurred(env)) {
174         JNU_ThrowByName(env, name, defaultDetail);
175     }
176 }
177 
178 /* Throw an IOException, using the last-error string for the detail
179  * string.  If the last-error string is NULL, use the given default
180  * detail string.
181  */
182 JNIEXPORT void JNICALL
JNU_ThrowIOExceptionWithLastError(JNIEnv * env,const char * defaultDetail)183 JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail)
184 {
185     JNU_ThrowByNameWithLastError(env, "java/io/IOException", defaultDetail);
186 }
187 
188 
189 JNIEXPORT jvalue JNICALL
JNU_CallStaticMethodByName(JNIEnv * env,jboolean * hasException,const char * class_name,const char * name,const char * signature,...)190 JNU_CallStaticMethodByName(JNIEnv *env,
191                            jboolean *hasException,
192                            const char *class_name,
193                            const char *name,
194                            const char *signature,
195                            ...)
196 {
197     jclass clazz;
198     jmethodID mid;
199     va_list args;
200     jvalue result;
201     const char *p = signature;
202 
203     /* find out the return type */
204     while (*p && *p != ')')
205         p++;
206     p++;
207 
208     result.i = 0;
209 
210     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
211         goto done2;
212 
213     clazz = (*env)->FindClass(env, class_name);
214     if (clazz == 0)
215         goto done2;
216     mid = (*env)->GetStaticMethodID(env, clazz, name, signature);
217     if (mid == 0)
218         goto done1;
219     va_start(args, signature);
220     switch (*p) {
221     case 'V':
222         (*env)->CallStaticVoidMethodV(env, clazz, mid, args);
223         break;
224     case '[':
225     case 'L':
226         result.l = (*env)->CallStaticObjectMethodV(env, clazz, mid, args);
227         break;
228     case 'Z':
229         result.z = (*env)->CallStaticBooleanMethodV(env, clazz, mid, args);
230         break;
231     case 'B':
232         result.b = (*env)->CallStaticByteMethodV(env, clazz, mid, args);
233         break;
234     case 'C':
235         result.c = (*env)->CallStaticCharMethodV(env, clazz, mid, args);
236         break;
237     case 'S':
238         result.s = (*env)->CallStaticShortMethodV(env, clazz, mid, args);
239         break;
240     case 'I':
241         result.i = (*env)->CallStaticIntMethodV(env, clazz, mid, args);
242         break;
243     case 'J':
244         result.j = (*env)->CallStaticLongMethodV(env, clazz, mid, args);
245         break;
246     case 'F':
247         result.f = (*env)->CallStaticFloatMethodV(env, clazz, mid, args);
248         break;
249     case 'D':
250         result.d = (*env)->CallStaticDoubleMethodV(env, clazz, mid, args);
251         break;
252     default:
253         (*env)->FatalError(env, "JNU_CallStaticMethodByName: illegal signature");
254     }
255     va_end(args);
256 
257  done1:
258     (*env)->DeleteLocalRef(env, clazz);
259  done2:
260     if (hasException) {
261         *hasException = (*env)->ExceptionCheck(env);
262     }
263     return result;
264 }
265 
266 JNIEXPORT jvalue JNICALL
JNU_CallMethodByName(JNIEnv * env,jboolean * hasException,jobject obj,const char * name,const char * signature,...)267 JNU_CallMethodByName(JNIEnv *env,
268                      jboolean *hasException,
269                      jobject obj,
270                      const char *name,
271                      const char *signature,
272                      ...)
273 {
274     jvalue result;
275     va_list args;
276 
277     va_start(args, signature);
278     result = JNU_CallMethodByNameV(env, hasException, obj, name, signature,
279                                    args);
280     va_end(args);
281 
282     return result;
283 }
284 
285 
286 JNIEXPORT jvalue JNICALL
JNU_CallMethodByNameV(JNIEnv * env,jboolean * hasException,jobject obj,const char * name,const char * signature,va_list args)287 JNU_CallMethodByNameV(JNIEnv *env,
288                       jboolean *hasException,
289                       jobject obj,
290                       const char *name,
291                       const char *signature,
292                       va_list args)
293 {
294     jclass clazz;
295     jmethodID mid;
296     jvalue result;
297     const char *p = signature;
298 
299     /* find out the return type */
300     while (*p && *p != ')')
301         p++;
302     p++;
303 
304     result.i = 0;
305 
306     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
307         goto done2;
308 
309     clazz = (*env)->GetObjectClass(env, obj);
310     mid = (*env)->GetMethodID(env, clazz, name, signature);
311     if (mid == 0)
312         goto done1;
313 
314     switch (*p) {
315     case 'V':
316         (*env)->CallVoidMethodV(env, obj, mid, args);
317         break;
318     case '[':
319     case 'L':
320         result.l = (*env)->CallObjectMethodV(env, obj, mid, args);
321         break;
322     case 'Z':
323         result.z = (*env)->CallBooleanMethodV(env, obj, mid, args);
324         break;
325     case 'B':
326         result.b = (*env)->CallByteMethodV(env, obj, mid, args);
327         break;
328     case 'C':
329         result.c = (*env)->CallCharMethodV(env, obj, mid, args);
330         break;
331     case 'S':
332         result.s = (*env)->CallShortMethodV(env, obj, mid, args);
333         break;
334     case 'I':
335         result.i = (*env)->CallIntMethodV(env, obj, mid, args);
336         break;
337     case 'J':
338         result.j = (*env)->CallLongMethodV(env, obj, mid, args);
339         break;
340     case 'F':
341         result.f = (*env)->CallFloatMethodV(env, obj, mid, args);
342         break;
343     case 'D':
344         result.d = (*env)->CallDoubleMethodV(env, obj, mid, args);
345         break;
346     default:
347         (*env)->FatalError(env, "JNU_CallMethodByNameV: illegal signature");
348     }
349  done1:
350     (*env)->DeleteLocalRef(env, clazz);
351  done2:
352     if (hasException) {
353         *hasException = (*env)->ExceptionCheck(env);
354     }
355     return result;
356 }
357 
358 JNIEXPORT jobject JNICALL
JNU_NewObjectByName(JNIEnv * env,const char * class_name,const char * constructor_sig,...)359 JNU_NewObjectByName(JNIEnv *env, const char *class_name,
360                     const char *constructor_sig, ...)
361 {
362     jobject obj = NULL;
363 
364     jclass cls = 0;
365     jmethodID cls_initMID;
366     va_list args;
367 
368     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
369         goto done;
370 
371     cls = (*env)->FindClass(env, class_name);
372     if (cls == 0) {
373         goto done;
374     }
375     cls_initMID  = (*env)->GetMethodID(env, cls,
376                                        "<init>", constructor_sig);
377     if (cls_initMID == NULL) {
378         goto done;
379     }
380     va_start(args, constructor_sig);
381     obj = (*env)->NewObjectV(env, cls, cls_initMID, args);
382     va_end(args);
383 
384  done:
385     (*env)->DeleteLocalRef(env, cls);
386     return obj;
387 }
388 
389 // Android removed: Deal solely in UTF-8
390 //
391 // /* Optimized for char set ISO_8559_1 */
392 // static jstring
393 // newString8859_1(JNIEnv *env, const char *str)
394 // {
395 //     int len = (int)strlen(str);
396 //     jchar buf[512];
397 //     jchar *str1;
398 //     jstring result;
399 //     int i;
400 //
401 //     if (len > 512) {
402 //         str1 = (jchar *)malloc(len * sizeof(jchar));
403 //         if (str1 == 0) {
404 //             JNU_ThrowOutOfMemoryError(env, 0);
405 //             return 0;
406 //         }
407 //     } else
408 //         str1 = buf;
409 //
410 //     for (i=0;i<len;i++)
411 //         str1[i] = (unsigned char)str[i];
412 //     result = (*env)->NewString(env, str1, len);
413 //     if (str1 != buf)
414 //         free(str1);
415 //     return result;
416 // }
417 //
418 // static const char*
419 // getString8859_1Chars(JNIEnv *env, jstring jstr)
420 // {
421 //     int i;
422 //     char *result;
423 //     jint len = (*env)->GetStringLength(env, jstr);
424 //     const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
425 //     if (str == 0) {
426 //         return 0;
427 //     }
428 //
429 //     result = MALLOC_MIN4(len);
430 //     if (result == 0) {
431 //         (*env)->ReleaseStringCritical(env, jstr, str);
432 //         JNU_ThrowOutOfMemoryError(env, 0);
433 //         return 0;
434 //     }
435 //
436 //     for (i=0; i<len; i++) {
437 //         jchar unicode = str[i];
438 //         if (unicode <= 0x00ff)
439 //             result[i] = (char)unicode;
440 //         else
441 //             result[i] = '?';
442 //     }
443 //
444 //     result[len] = 0;
445 //     (*env)->ReleaseStringCritical(env, jstr, str);
446 //     return result;
447 // }
448 //
449 //
450 // /* Optimized for char set ISO646-US (us-ascii) */
451 // static jstring
452 // newString646_US(JNIEnv *env, const char *str)
453 // {
454 //     int len = strlen(str);
455 //     jchar buf[512];
456 //     jchar *str1;
457 //     jstring result;
458 //     int i;
459 //
460 //     if (len > 512) {
461 //         str1 = (jchar *)malloc(len * sizeof(jchar));
462 //         if (str1 == 0) {
463 //             JNU_ThrowOutOfMemoryError(env, 0);
464 //             return 0;
465 //         }
466 //     } else
467 //         str1 = buf;
468 //
469 //     for (i=0; i<len; i++) {
470 //         unsigned char c = (unsigned char)str[i];
471 //         if (c <= 0x7f)
472 //             str1[i] = c;
473 //         else
474 //             str1[i] = '?';
475 //     }
476 //
477 //     result = (*env)->NewString(env, str1, len);
478 //     if (str1 != buf)
479 //         free(str1);
480 //     return result;
481 // }
482 //
483 // static const char*
484 // getString646_USChars(JNIEnv *env, jstring jstr)
485 // {
486 //     int i;
487 //     char *result;
488 //     jint len = (*env)->GetStringLength(env, jstr);
489 //     const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
490 //     if (str == 0) {
491 //         return 0;
492 //     }
493 //
494 //     result = MALLOC_MIN4(len);
495 //     if (result == 0) {
496 //         (*env)->ReleaseStringCritical(env, jstr, str);
497 //         JNU_ThrowOutOfMemoryError(env, 0);
498 //         return 0;
499 //     }
500 //
501 //     for (i=0; i<len; i++) {
502 //         jchar unicode = str[i];
503 //         if (unicode <= 0x007f )
504 //             result[i] = (char)unicode;
505 //         else
506 //             result[i] = '?';
507 //     }
508 //
509 //     result[len] = 0;
510 //     (*env)->ReleaseStringCritical(env, jstr, str);
511 //     return result;
512 // }
513 //
514 // /* enumeration of c1 row from Cp1252 */
515 // static int cp1252c1chars[32] = {
516 //     0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,
517 //     0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
518 //     0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
519 //     0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
520 // };
521 //
522 // /* Optimized for char set Cp1252 */
523 // static jstring
524 // newStringCp1252(JNIEnv *env, const char *str)
525 // {
526 //     int len = (int) strlen(str);
527 //     jchar buf[512];
528 //     jchar *str1;
529 //     jstring result;
530 //     int i;
531 //     if (len > 512) {
532 //         str1 = (jchar *)malloc(len * sizeof(jchar));
533 //         if (str1 == 0) {
534 //             JNU_ThrowOutOfMemoryError(env, 0);
535 //             return 0;
536 //         }
537 //     } else
538 //         str1 = buf;
539 //
540 //     for (i=0; i<len; i++) {
541 //         unsigned char c = (unsigned char)str[i];
542 //         if ((c >= 0x80) && (c <= 0x9f))
543 //             str1[i] = cp1252c1chars[c-128];
544 //         else
545 //             str1[i] = c;
546 //     }
547 //
548 //     result = (*env)->NewString(env, str1, len);
549 //     if (str1 != buf)
550 //         free(str1);
551 //     return result;
552 // }
553 //
554 // static const char*
555 // getStringCp1252Chars(JNIEnv *env, jstring jstr)
556 // {
557 //     int i;
558 //     char *result;
559 //     jint len = (*env)->GetStringLength(env, jstr);
560 //     const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
561 //     if (str == 0) {
562 //         return 0;
563 //     }
564 //
565 //     result = MALLOC_MIN4(len);
566 //     if (result == 0) {
567 //         (*env)->ReleaseStringCritical(env, jstr, str);
568 //         JNU_ThrowOutOfMemoryError(env, 0);
569 //         return 0;
570 //     }
571 //
572 //     for (i=0; i<len; i++) {
573 //         jchar c = str[i];
574 //         if (c < 256)
575 //             result[i] = (char)c;
576 //         else switch(c) {
577 //             case 0x20AC: result[i] = (char)0x80; break;
578 //             case 0x201A: result[i] = (char)0x82; break;
579 //             case 0x0192: result[i] = (char)0x83; break;
580 //             case 0x201E: result[i] = (char)0x84; break;
581 //             case 0x2026: result[i] = (char)0x85; break;
582 //             case 0x2020: result[i] = (char)0x86; break;
583 //             case 0x2021: result[i] = (char)0x87; break;
584 //             case 0x02C6: result[i] = (char)0x88; break;
585 //             case 0x2030: result[i] = (char)0x89; break;
586 //             case 0x0160: result[i] = (char)0x8A; break;
587 //             case 0x2039: result[i] = (char)0x8B; break;
588 //             case 0x0152: result[i] = (char)0x8C; break;
589 //             case 0x017D: result[i] = (char)0x8E; break;
590 //             case 0x2018: result[i] = (char)0x91; break;
591 //             case 0x2019: result[i] = (char)0x92; break;
592 //             case 0x201C: result[i] = (char)0x93; break;
593 //             case 0x201D: result[i] = (char)0x94; break;
594 //             case 0x2022: result[i] = (char)0x95; break;
595 //             case 0x2013: result[i] = (char)0x96; break;
596 //             case 0x2014: result[i] = (char)0x97; break;
597 //             case 0x02DC: result[i] = (char)0x98; break;
598 //             case 0x2122: result[i] = (char)0x99; break;
599 //             case 0x0161: result[i] = (char)0x9A; break;
600 //             case 0x203A: result[i] = (char)0x9B; break;
601 //             case 0x0153: result[i] = (char)0x9C; break;
602 //             case 0x017E: result[i] = (char)0x9E; break;
603 //             case 0x0178: result[i] = (char)0x9F; break;
604 //             default:     result[i] = '?';  break;
605 //         }
606 //     }
607 //
608 //     result[len] = 0;
609 //     (*env)->ReleaseStringCritical(env, jstr, str);
610 //     return result;
611 // }
612 //
613 // static int fastEncoding = NO_ENCODING_YET;
614 // static jstring jnuEncoding = NULL;
615 //
616 // /* Cached method IDs */
617 // static jmethodID String_init_ID;        /* String(byte[], enc) */
618 // static jmethodID String_getBytes_ID;    /* String.getBytes(enc) */
619 //
620 // int getFastEncoding() {
621 //     return fastEncoding;
622 // }
623 //
624 // /* Initialize the fast encoding.  If the "sun.jnu.encoding" property
625 //  * has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
626 //  */
627 // void
628 // initializeEncoding(JNIEnv *env)
629 // {
630 //     jstring propname = 0;
631 //     jstring enc = 0;
632 //
633 //     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
634 //         return;
635 //
636 //     propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
637 //     if (propname) {
638 //         jboolean exc;
639 //         enc = JNU_CallStaticMethodByName
640 //                        (env,
641 //                         &exc,
642 //                         "java/lang/System",
643 //                         "getProperty",
644 //                         "(Ljava/lang/String;)Ljava/lang/String;",
645 //                         propname).l;
646 //         if (!exc) {
647 //             if (enc) {
648 //                 const char* encname = (*env)->GetStringUTFChars(env, enc, 0);
649 //                 if (encname) {
650 //            /*
651 //             * On Solaris with nl_langinfo() called in GetJavaProperties():
652 //             *
653 //             *   locale undefined -> NULL -> hardcoded default
654 //             *   "C" locale       -> "" -> hardcoded default     (on 2.6)
655 //             *   "C" locale       -> "ISO646-US"                 (on Sol 7/8)
656 //             *   "en_US" locale -> "ISO8859-1"
657 //             *   "en_GB" locale -> "ISO8859-1"                   (on Sol 7/8)
658 //             *   "en_UK" locale -> "ISO8859-1"                   (on 2.6)
659 //             */
660 //                     if ((strcmp(encname, "8859_1") == 0) ||
661 //                         (strcmp(encname, "ISO8859-1") == 0) ||
662 //                         (strcmp(encname, "ISO8859_1") == 0))
663 //                         fastEncoding = FAST_8859_1;
664 //                     else if (strcmp(encname, "ISO646-US") == 0)
665 //                         fastEncoding = FAST_646_US;
666 //                     else if (strcmp(encname, "Cp1252") == 0 ||
667 //                              /* This is a temporary fix until we move */
668 //                              /* to wide character versions of all Windows */
669 //                              /* calls. */
670 //                              strcmp(encname, "utf-16le") == 0)
671 //                         fastEncoding = FAST_CP1252;
672 //                     else {
673 //                         fastEncoding = NO_FAST_ENCODING;
674 //                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
675 //                     }
676 //                     (*env)->ReleaseStringUTFChars(env, enc, encname);
677 //                 }
678 //             }
679 //         } else {
680 //             (*env)->ExceptionClear(env);
681 //         }
682 //     } else {
683 //         (*env)->ExceptionClear(env);
684 //     }
685 //     (*env)->DeleteLocalRef(env, propname);
686 //     (*env)->DeleteLocalRef(env, enc);
687 //
688 //     /* Initialize method-id cache */
689 //     String_getBytes_ID = (*env)->GetMethodID(env, JNU_ClassString(env),
690 //                                              "getBytes", "(Ljava/lang/String;)[B");
691 //     String_init_ID = (*env)->GetMethodID(env, JNU_ClassString(env),
692 //                                          "<init>", "([BLjava/lang/String;)V");
693 // }
694 //
695 // static jboolean isJNUEncodingSupported = JNI_FALSE;
696 // static jboolean jnuEncodingSupported(JNIEnv *env) {
697 //     jboolean exe;
698 //     if (isJNUEncodingSupported == JNI_TRUE) {
699 //         return JNI_TRUE;
700 //     }
701 //     isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
702 //                                     env, &exe,
703 //                                     "java/nio/charset/Charset",
704 //                                     "isSupported",
705 //                                     "(Ljava/lang/String;)Z",
706 //                                     jnuEncoding).z;
707 //     return isJNUEncodingSupported;
708 // }
709 
710 
711 JNIEXPORT jstring
JNU_NewStringPlatform(JNIEnv * env,const char * str)712 JNU_NewStringPlatform(JNIEnv *env, const char *str)
713 {
714     // Android-changed: Always use nativeNewStringPlatform.
715     // return JNU_NewStringPlatform(env, str);
716     return nativeNewStringPlatform(env, str);
717 }
718 
719 JNIEXPORT const char *
JNU_GetStringPlatformChars(JNIEnv * env,jstring jstr,jboolean * isCopy)720 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
721 {
722     // Android-changed: Always use nativeGetStringPlatformChars.
723     // return JNU_GetStringPlatformChars(env, jstr, isCopy);
724     return nativeGetStringPlatformChars(env, jstr, isCopy);
725 }
726 
727 JNIEXPORT void JNICALL
JNU_ReleaseStringPlatformChars(JNIEnv * env,jstring jstr,const char * str)728 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
729 {
730     // Android changed : Use the "native" code from the platform a chance
731     // to handle this first.
732     //
733     // free((void *)str);
734     nativeReleaseStringPlatformChars(env, jstr, str);
735 }
736 
737 // Android removed: Deal solely in UTF-8
738 //
739 // JNIEXPORT jstring JNICALL
740 // JNU_NewStringPlatform(JNIEnv *env, const char *str)
741 // {
742 //    jstring result;
743 //    result = nativeNewStringPlatform(env, str);
744 //    if (result == NULL) {
745 //        jbyteArray hab = 0;
746 //        int len;
747 //
748 //        if (fastEncoding == NO_ENCODING_YET)
749 //            initializeEncoding(env);
750 //
751 //        if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
752 //            return newString8859_1(env, str);
753 //        if (fastEncoding == FAST_646_US)
754 //            return newString646_US(env, str);
755 //        if (fastEncoding == FAST_CP1252)
756 //            return newStringCp1252(env, str);
757 //
758 //        if ((*env)->EnsureLocalCapacity(env, 2) < 0)
759 //            return NULL;
760 //
761 //        len = (int)strlen(str);
762 //        hab = (*env)->NewByteArray(env, len);
763 //        if (hab != 0) {
764 //            (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
765 //            if (jnuEncodingSupported(env)) {
766 //                result = (*env)->NewObject(env, JNU_ClassString(env),
767 //                                           String_init_ID, hab, jnuEncoding);
768 //            } else {
769 //                /*If the encoding specified in sun.jnu.encoding is not endorsed
770 //                  by "Charset.isSupported" we have to fall back to use String(byte[])
771 //                  explicitly here without specifying the encoding name, in which the
772 //                  StringCoding class will pickup the iso-8859-1 as the fallback
773 //                  converter for us.
774 //                 */
775 //                jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
776 //                                                    "<init>", "([B)V");
777 //                result = (*env)->NewObject(env, JNU_ClassString(env), mid, hab);
778 //            }
779 //            (*env)->DeleteLocalRef(env, hab);
780 //            return result;
781 //        }
782 //    }
783 //    return NULL;
784 //}
785 //
786 //
787 //JNIEXPORT const char * JNICALL
788 //JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
789 //{
790 //    char *result = nativeGetStringPlatformChars(env, jstr, isCopy);
791 //    if (result == NULL) {
792 //
793 //        jbyteArray hab = 0;
794 //
795 //        if (isCopy)
796 //            *isCopy = JNI_TRUE;
797 //
798 //        if (fastEncoding == NO_ENCODING_YET)
799 //            initializeEncoding(env);
800 //
801 //        if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
802 //            return getString8859_1Chars(env, jstr);
803 //        if (fastEncoding == FAST_646_US)
804 //            return getString646_USChars(env, jstr);
805 //        if (fastEncoding == FAST_CP1252)
806 //            return getStringCp1252Chars(env, jstr);
807 //
808 //        if ((*env)->EnsureLocalCapacity(env, 2) < 0)
809 //            return 0;
810 //
811 //        if (jnuEncodingSupported(env)) {
812 //            hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
813 //        } else {
814 //            jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
815 //                                                "getBytes", "()[B");
816 //            hab = (*env)->CallObjectMethod(env, jstr, mid);
817 //        }
818 //
819 //        if (!(*env)->ExceptionCheck(env)) {
820 //            jint len = (*env)->GetArrayLength(env, hab);
821 //            result = MALLOC_MIN4(len);
822 //            if (result == 0) {
823 //                JNU_ThrowOutOfMemoryError(env, 0);
824 //                (*env)->DeleteLocalRef(env, hab);
825 //                return 0;
826 //            }
827 //            (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
828 //            result[len] = 0; /* NULL-terminate */
829 //        }
830 //
831 //        (*env)->DeleteLocalRef(env, hab);
832 //    }
833 //    return result;
834 //}
835 
836 
837 /*
838  * Export the platform dependent path canonicalization so that
839  * VM can find it when loading system classes.
840  *
841  */
842 // Android-changed: hidden to avoid conflict with libm (b/135018555)
843 __attribute__((visibility("hidden")))
844 extern int canonicalize(char *path, const char *out, int len);
845 
846 JNIEXPORT int
Canonicalize(JNIEnv * env,char * orig,char * out,int len)847 Canonicalize(JNIEnv *env, char *orig, char *out, int len)
848 {
849     /* canonicalize an already natived path */
850     return canonicalize(orig, out, len);
851 }
852 
853 JNIEXPORT jclass JNICALL
JNU_ClassString(JNIEnv * env)854 JNU_ClassString(JNIEnv *env)
855 {
856     static jclass cls = 0;
857     if (cls == 0) {
858         jclass c;
859         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
860             return 0;
861         c = (*env)->FindClass(env, "java/lang/String");
862         cls = (*env)->NewGlobalRef(env, c);
863         (*env)->DeleteLocalRef(env, c);
864     }
865     return cls;
866 }
867 
868 JNIEXPORT jclass JNICALL
JNU_ClassClass(JNIEnv * env)869 JNU_ClassClass(JNIEnv *env)
870 {
871     static jclass cls = 0;
872     if (cls == 0) {
873         jclass c;
874         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
875             return 0;
876         c = (*env)->FindClass(env, "java/lang/Class");
877         cls = (*env)->NewGlobalRef(env, c);
878         (*env)->DeleteLocalRef(env, c);
879     }
880     return cls;
881 }
882 
883 JNIEXPORT jclass JNICALL
JNU_ClassObject(JNIEnv * env)884 JNU_ClassObject(JNIEnv *env)
885 {
886     static jclass cls = 0;
887     if (cls == 0) {
888         jclass c;
889         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
890             return 0;
891         c = (*env)->FindClass(env, "java/lang/Object");
892         cls = (*env)->NewGlobalRef(env, c);
893         (*env)->DeleteLocalRef(env, c);
894     }
895     return cls;
896 }
897 
898 JNIEXPORT jclass JNICALL
JNU_ClassThrowable(JNIEnv * env)899 JNU_ClassThrowable(JNIEnv *env)
900 {
901     static jclass cls = 0;
902     if (cls == 0) {
903         jclass c;
904         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
905             return 0;
906         c = (*env)->FindClass(env, "java/lang/Throwable");
907         cls = (*env)->NewGlobalRef(env, c);
908         (*env)->DeleteLocalRef(env, c);
909     }
910     return cls;
911 }
912 
913 JNIEXPORT jint JNICALL
JNU_CopyObjectArray(JNIEnv * env,jobjectArray dst,jobjectArray src,jint count)914 JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
915                          jint count)
916 {
917     int i;
918     if ((*env)->EnsureLocalCapacity(env, 1) < 0)
919         return -1;
920     for (i=0; i<count; i++) {
921         jstring p = (*env)->GetObjectArrayElement(env, src, i);
922         (*env)->SetObjectArrayElement(env, dst, i, p);
923         (*env)->DeleteLocalRef(env, p);
924     }
925     return 0;
926 }
927 
928 JNIEXPORT void * JNICALL
JNU_GetEnv(JavaVM * vm,jint version)929 JNU_GetEnv(JavaVM *vm, jint version)
930 {
931     void *env;
932     (*vm)->GetEnv(vm, &env, version);
933     return env;
934 }
935 
936 JNIEXPORT jint JNICALL
JNU_IsInstanceOfByName(JNIEnv * env,jobject object,char * classname)937 JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char* classname)
938 {
939     jclass cls;
940     if ((*env)->EnsureLocalCapacity(env, 1) < 0)
941         return JNI_ERR;
942     cls = (*env)->FindClass(env, classname);
943     if (cls != NULL) {
944         jint result = (*env)->IsInstanceOf(env, object, cls);
945         (*env)->DeleteLocalRef(env, cls);
946         return result;
947     }
948     return JNI_ERR;
949 }
950 
951 JNIEXPORT jboolean JNICALL
JNU_Equals(JNIEnv * env,jobject object1,jobject object2)952 JNU_Equals(JNIEnv *env, jobject object1, jobject object2)
953 {
954     static jmethodID mid = NULL;
955     if (mid == NULL) {
956         mid = (*env)->GetMethodID(env, JNU_ClassObject(env), "equals",
957                                   "(Ljava/lang/Object;)Z");
958     }
959     return (*env)->CallBooleanMethod(env, object1, mid, object2);
960 }
961 
962 
963 /************************************************************************
964  * Thread calls
965  */
966 
967 static jmethodID Object_waitMID;
968 static jmethodID Object_notifyMID;
969 static jmethodID Object_notifyAllMID;
970 
971 JNIEXPORT void JNICALL
JNU_MonitorWait(JNIEnv * env,jobject object,jlong timeout)972 JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout)
973 {
974     if (object == NULL) {
975         JNU_ThrowNullPointerException(env, "JNU_MonitorWait argument");
976         return;
977     }
978     if (Object_waitMID == NULL) {
979         jclass cls = JNU_ClassObject(env);
980         if (cls == NULL) {
981             return;
982         }
983         Object_waitMID = (*env)->GetMethodID(env, cls, "wait", "(J)V");
984         if (Object_waitMID == NULL) {
985             return;
986         }
987     }
988     (*env)->CallVoidMethod(env, object, Object_waitMID, timeout);
989 }
990 
991 JNIEXPORT void JNICALL
JNU_Notify(JNIEnv * env,jobject object)992 JNU_Notify(JNIEnv *env, jobject object)
993 {
994     if (object == NULL) {
995         JNU_ThrowNullPointerException(env, "JNU_Notify argument");
996         return;
997     }
998     if (Object_notifyMID == NULL) {
999         jclass cls = JNU_ClassObject(env);
1000         if (cls == NULL) {
1001             return;
1002         }
1003         Object_notifyMID = (*env)->GetMethodID(env, cls, "notify", "()V");
1004         if (Object_notifyMID == NULL) {
1005             return;
1006         }
1007     }
1008     (*env)->CallVoidMethod(env, object, Object_notifyMID);
1009 }
1010 
1011 JNIEXPORT void JNICALL
JNU_NotifyAll(JNIEnv * env,jobject object)1012 JNU_NotifyAll(JNIEnv *env, jobject object)
1013 {
1014     if (object == NULL) {
1015         JNU_ThrowNullPointerException(env, "JNU_NotifyAll argument");
1016         return;
1017     }
1018     if (Object_notifyAllMID == NULL) {
1019         jclass cls = JNU_ClassObject(env);
1020         if (cls == NULL) {
1021             return;
1022         }
1023         Object_notifyAllMID = (*env)->GetMethodID(env, cls,"notifyAll", "()V");
1024         if (Object_notifyAllMID == NULL) {
1025             return;
1026         }
1027     }
1028     (*env)->CallVoidMethod(env, object, Object_notifyAllMID);
1029 }
1030 
1031 
1032 /************************************************************************
1033  * Debugging utilities
1034  */
1035 
1036 JNIEXPORT void JNICALL
JNU_PrintString(JNIEnv * env,char * hdr,jstring string)1037 JNU_PrintString(JNIEnv *env, char *hdr, jstring string)
1038 {
1039     if (string == NULL) {
1040         fprintf(stderr, "%s: is NULL\n", hdr);
1041     } else {
1042         const char *stringPtr = JNU_GetStringPlatformChars(env, string, 0);
1043         if (stringPtr == 0)
1044             return;
1045         fprintf(stderr, "%s: %s\n", hdr, stringPtr);
1046         JNU_ReleaseStringPlatformChars(env, string, stringPtr);
1047     }
1048 }
1049 
1050 JNIEXPORT void JNICALL
JNU_PrintClass(JNIEnv * env,char * hdr,jobject object)1051 JNU_PrintClass(JNIEnv *env, char* hdr, jobject object)
1052 {
1053     if (object == NULL) {
1054         fprintf(stderr, "%s: object is NULL\n", hdr);
1055         return;
1056     } else {
1057         jclass cls = (*env)->GetObjectClass(env, object);
1058         jstring clsName = JNU_ToString(env, cls);
1059         JNU_PrintString(env, hdr, clsName);
1060         (*env)->DeleteLocalRef(env, cls);
1061         (*env)->DeleteLocalRef(env, clsName);
1062     }
1063 }
1064 
1065 JNIEXPORT jstring JNICALL
JNU_ToString(JNIEnv * env,jobject object)1066 JNU_ToString(JNIEnv *env, jobject object)
1067 {
1068     if (object == NULL) {
1069         return (*env)->NewStringUTF(env, "NULL");
1070     } else {
1071         return (jstring)JNU_CallMethodByName(env,
1072                                              NULL,
1073                                              object,
1074                                              "toString",
1075                                              "()Ljava/lang/String;").l;
1076     }
1077 }
1078 
1079 JNIEXPORT jvalue JNICALL
JNU_GetFieldByName(JNIEnv * env,jboolean * hasException,jobject obj,const char * name,const char * signature)1080 JNU_GetFieldByName(JNIEnv *env,
1081                    jboolean *hasException,
1082                    jobject obj,
1083                    const char *name,
1084                    const char *signature)
1085 {
1086     jclass cls;
1087     jfieldID fid;
1088     jvalue result;
1089 
1090     result.i = 0;
1091 
1092     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1093         goto done2;
1094 
1095     cls = (*env)->GetObjectClass(env, obj);
1096     fid = (*env)->GetFieldID(env, cls, name, signature);
1097     if (fid == 0)
1098         goto done1;
1099 
1100     switch (*signature) {
1101     case '[':
1102     case 'L':
1103         result.l = (*env)->GetObjectField(env, obj, fid);
1104         break;
1105     case 'Z':
1106         result.z = (*env)->GetBooleanField(env, obj, fid);
1107         break;
1108     case 'B':
1109         result.b = (*env)->GetByteField(env, obj, fid);
1110         break;
1111     case 'C':
1112         result.c = (*env)->GetCharField(env, obj, fid);
1113         break;
1114     case 'S':
1115         result.s = (*env)->GetShortField(env, obj, fid);
1116         break;
1117     case 'I':
1118         result.i = (*env)->GetIntField(env, obj, fid);
1119         break;
1120     case 'J':
1121         result.j = (*env)->GetLongField(env, obj, fid);
1122         break;
1123     case 'F':
1124         result.f = (*env)->GetFloatField(env, obj, fid);
1125         break;
1126     case 'D':
1127         result.d = (*env)->GetDoubleField(env, obj, fid);
1128         break;
1129 
1130     default:
1131         (*env)->FatalError(env, "JNU_GetFieldByName: illegal signature");
1132     }
1133 
1134  done1:
1135     (*env)->DeleteLocalRef(env, cls);
1136  done2:
1137     if (hasException) {
1138         *hasException = (*env)->ExceptionCheck(env);
1139     }
1140     return result;
1141 }
1142 
1143 JNIEXPORT void JNICALL
JNU_SetFieldByName(JNIEnv * env,jboolean * hasException,jobject obj,const char * name,const char * signature,...)1144 JNU_SetFieldByName(JNIEnv *env,
1145                    jboolean *hasException,
1146                    jobject obj,
1147                    const char *name,
1148                    const char *signature,
1149                    ...)
1150 {
1151     jclass cls;
1152     jfieldID fid;
1153     va_list args;
1154 
1155     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1156         goto done2;
1157 
1158     cls = (*env)->GetObjectClass(env, obj);
1159     fid = (*env)->GetFieldID(env, cls, name, signature);
1160     if (fid == 0)
1161         goto done1;
1162 
1163     va_start(args, signature);
1164     switch (*signature) {
1165     case '[':
1166     case 'L':
1167         (*env)->SetObjectField(env, obj, fid, va_arg(args, jobject));
1168         break;
1169     case 'Z':
1170         (*env)->SetBooleanField(env, obj, fid, (jboolean)va_arg(args, int));
1171         break;
1172     case 'B':
1173         (*env)->SetByteField(env, obj, fid, (jbyte)va_arg(args, int));
1174         break;
1175     case 'C':
1176         (*env)->SetCharField(env, obj, fid, (jchar)va_arg(args, int));
1177         break;
1178     case 'S':
1179         (*env)->SetShortField(env, obj, fid, (jshort)va_arg(args, int));
1180         break;
1181     case 'I':
1182         (*env)->SetIntField(env, obj, fid, va_arg(args, jint));
1183         break;
1184     case 'J':
1185         (*env)->SetLongField(env, obj, fid, va_arg(args, jlong));
1186         break;
1187     case 'F':
1188         (*env)->SetFloatField(env, obj, fid, (jfloat)va_arg(args, jdouble));
1189         break;
1190     case 'D':
1191         (*env)->SetDoubleField(env, obj, fid, va_arg(args, jdouble));
1192         break;
1193 
1194     default:
1195         (*env)->FatalError(env, "JNU_SetFieldByName: illegal signature");
1196     }
1197     va_end(args);
1198 
1199  done1:
1200     (*env)->DeleteLocalRef(env, cls);
1201  done2:
1202     if (hasException) {
1203         *hasException = (*env)->ExceptionCheck(env);
1204     }
1205 }
1206 
1207 JNIEXPORT jvalue JNICALL
JNU_GetStaticFieldByName(JNIEnv * env,jboolean * hasException,const char * classname,const char * name,const char * signature)1208 JNU_GetStaticFieldByName(JNIEnv *env,
1209                          jboolean *hasException,
1210                          const char *classname,
1211                          const char *name,
1212                          const char *signature)
1213 {
1214     jclass cls;
1215     jfieldID fid;
1216     jvalue result;
1217 
1218     result.i = 0;
1219 
1220     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1221         goto done2;
1222 
1223     cls = (*env)->FindClass(env, classname);
1224     if (cls == 0)
1225         goto done2;
1226 
1227     fid = (*env)->GetStaticFieldID(env, cls, name, signature);
1228     if (fid == 0)
1229         goto done1;
1230 
1231     switch (*signature) {
1232     case '[':
1233     case 'L':
1234         result.l = (*env)->GetStaticObjectField(env, cls, fid);
1235         break;
1236     case 'Z':
1237         result.z = (*env)->GetStaticBooleanField(env, cls, fid);
1238         break;
1239     case 'B':
1240         result.b = (*env)->GetStaticByteField(env, cls, fid);
1241         break;
1242     case 'C':
1243         result.c = (*env)->GetStaticCharField(env, cls, fid);
1244         break;
1245     case 'S':
1246         result.s = (*env)->GetStaticShortField(env, cls, fid);
1247         break;
1248     case 'I':
1249         result.i = (*env)->GetStaticIntField(env, cls, fid);
1250         break;
1251     case 'J':
1252         result.j = (*env)->GetStaticLongField(env, cls, fid);
1253         break;
1254     case 'F':
1255         result.f = (*env)->GetStaticFloatField(env, cls, fid);
1256         break;
1257     case 'D':
1258         result.d = (*env)->GetStaticDoubleField(env, cls, fid);
1259         break;
1260 
1261     default:
1262         (*env)->FatalError(env, "JNU_GetStaticFieldByName: illegal signature");
1263     }
1264 
1265  done1:
1266     (*env)->DeleteLocalRef(env, cls);
1267  done2:
1268     if (hasException) {
1269         *hasException = (*env)->ExceptionCheck(env);
1270     }
1271     return result;
1272 }
1273 
1274 JNIEXPORT void JNICALL
JNU_SetStaticFieldByName(JNIEnv * env,jboolean * hasException,const char * classname,const char * name,const char * signature,...)1275 JNU_SetStaticFieldByName(JNIEnv *env,
1276                          jboolean *hasException,
1277                          const char *classname,
1278                          const char *name,
1279                          const char *signature,
1280                          ...)
1281 {
1282     jclass cls;
1283     jfieldID fid;
1284     va_list args;
1285 
1286     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1287         goto done2;
1288 
1289     cls = (*env)->FindClass(env, classname);
1290     if (cls == 0)
1291         goto done2;
1292 
1293     fid = (*env)->GetStaticFieldID(env, cls, name, signature);
1294     if (fid == 0)
1295         goto done1;
1296 
1297     va_start(args, signature);
1298     switch (*signature) {
1299     case '[':
1300     case 'L':
1301         (*env)->SetStaticObjectField(env, cls, fid, va_arg(args, jobject));
1302         break;
1303     case 'Z':
1304         (*env)->SetStaticBooleanField(env, cls, fid, (jboolean)va_arg(args, int));
1305         break;
1306     case 'B':
1307         (*env)->SetStaticByteField(env, cls, fid, (jbyte)va_arg(args, int));
1308         break;
1309     case 'C':
1310         (*env)->SetStaticCharField(env, cls, fid, (jchar)va_arg(args, int));
1311         break;
1312     case 'S':
1313         (*env)->SetStaticShortField(env, cls, fid, (jshort)va_arg(args, int));
1314         break;
1315     case 'I':
1316         (*env)->SetStaticIntField(env, cls, fid, va_arg(args, jint));
1317         break;
1318     case 'J':
1319         (*env)->SetStaticLongField(env, cls, fid, va_arg(args, jlong));
1320         break;
1321     case 'F':
1322         (*env)->SetStaticFloatField(env, cls, fid, (jfloat)va_arg(args, jdouble));
1323         break;
1324     case 'D':
1325         (*env)->SetStaticDoubleField(env, cls, fid, va_arg(args, jdouble));
1326         break;
1327 
1328     default:
1329         (*env)->FatalError(env, "JNU_SetStaticFieldByName: illegal signature");
1330     }
1331     va_end(args);
1332 
1333  done1:
1334     (*env)->DeleteLocalRef(env, cls);
1335  done2:
1336     if (hasException) {
1337         *hasException = (*env)->ExceptionCheck(env);
1338     }
1339 }
1340