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 extern int canonicalize(char *path, const char *out, int len);
843 
844 JNIEXPORT int
Canonicalize(JNIEnv * env,char * orig,char * out,int len)845 Canonicalize(JNIEnv *env, char *orig, char *out, int len)
846 {
847     /* canonicalize an already natived path */
848     return canonicalize(orig, out, len);
849 }
850 
851 JNIEXPORT jclass JNICALL
JNU_ClassString(JNIEnv * env)852 JNU_ClassString(JNIEnv *env)
853 {
854     static jclass cls = 0;
855     if (cls == 0) {
856         jclass c;
857         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
858             return 0;
859         c = (*env)->FindClass(env, "java/lang/String");
860         cls = (*env)->NewGlobalRef(env, c);
861         (*env)->DeleteLocalRef(env, c);
862     }
863     return cls;
864 }
865 
866 JNIEXPORT jclass JNICALL
JNU_ClassClass(JNIEnv * env)867 JNU_ClassClass(JNIEnv *env)
868 {
869     static jclass cls = 0;
870     if (cls == 0) {
871         jclass c;
872         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
873             return 0;
874         c = (*env)->FindClass(env, "java/lang/Class");
875         cls = (*env)->NewGlobalRef(env, c);
876         (*env)->DeleteLocalRef(env, c);
877     }
878     return cls;
879 }
880 
881 JNIEXPORT jclass JNICALL
JNU_ClassObject(JNIEnv * env)882 JNU_ClassObject(JNIEnv *env)
883 {
884     static jclass cls = 0;
885     if (cls == 0) {
886         jclass c;
887         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
888             return 0;
889         c = (*env)->FindClass(env, "java/lang/Object");
890         cls = (*env)->NewGlobalRef(env, c);
891         (*env)->DeleteLocalRef(env, c);
892     }
893     return cls;
894 }
895 
896 JNIEXPORT jclass JNICALL
JNU_ClassThrowable(JNIEnv * env)897 JNU_ClassThrowable(JNIEnv *env)
898 {
899     static jclass cls = 0;
900     if (cls == 0) {
901         jclass c;
902         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
903             return 0;
904         c = (*env)->FindClass(env, "java/lang/Throwable");
905         cls = (*env)->NewGlobalRef(env, c);
906         (*env)->DeleteLocalRef(env, c);
907     }
908     return cls;
909 }
910 
911 JNIEXPORT jint JNICALL
JNU_CopyObjectArray(JNIEnv * env,jobjectArray dst,jobjectArray src,jint count)912 JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
913                          jint count)
914 {
915     int i;
916     if ((*env)->EnsureLocalCapacity(env, 1) < 0)
917         return -1;
918     for (i=0; i<count; i++) {
919         jstring p = (*env)->GetObjectArrayElement(env, src, i);
920         (*env)->SetObjectArrayElement(env, dst, i, p);
921         (*env)->DeleteLocalRef(env, p);
922     }
923     return 0;
924 }
925 
926 JNIEXPORT void * JNICALL
JNU_GetEnv(JavaVM * vm,jint version)927 JNU_GetEnv(JavaVM *vm, jint version)
928 {
929     void *env;
930     (*vm)->GetEnv(vm, &env, version);
931     return env;
932 }
933 
934 JNIEXPORT jint JNICALL
JNU_IsInstanceOfByName(JNIEnv * env,jobject object,char * classname)935 JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char* classname)
936 {
937     jclass cls;
938     if ((*env)->EnsureLocalCapacity(env, 1) < 0)
939         return JNI_ERR;
940     cls = (*env)->FindClass(env, classname);
941     if (cls != NULL) {
942         jint result = (*env)->IsInstanceOf(env, object, cls);
943         (*env)->DeleteLocalRef(env, cls);
944         return result;
945     }
946     return JNI_ERR;
947 }
948 
949 JNIEXPORT jboolean JNICALL
JNU_Equals(JNIEnv * env,jobject object1,jobject object2)950 JNU_Equals(JNIEnv *env, jobject object1, jobject object2)
951 {
952     static jmethodID mid = NULL;
953     if (mid == NULL) {
954         mid = (*env)->GetMethodID(env, JNU_ClassObject(env), "equals",
955                                   "(Ljava/lang/Object;)Z");
956     }
957     return (*env)->CallBooleanMethod(env, object1, mid, object2);
958 }
959 
960 
961 /************************************************************************
962  * Thread calls
963  */
964 
965 static jmethodID Object_waitMID;
966 static jmethodID Object_notifyMID;
967 static jmethodID Object_notifyAllMID;
968 
969 JNIEXPORT void JNICALL
JNU_MonitorWait(JNIEnv * env,jobject object,jlong timeout)970 JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout)
971 {
972     if (object == NULL) {
973         JNU_ThrowNullPointerException(env, "JNU_MonitorWait argument");
974         return;
975     }
976     if (Object_waitMID == NULL) {
977         jclass cls = JNU_ClassObject(env);
978         if (cls == NULL) {
979             return;
980         }
981         Object_waitMID = (*env)->GetMethodID(env, cls, "wait", "(J)V");
982         if (Object_waitMID == NULL) {
983             return;
984         }
985     }
986     (*env)->CallVoidMethod(env, object, Object_waitMID, timeout);
987 }
988 
989 JNIEXPORT void JNICALL
JNU_Notify(JNIEnv * env,jobject object)990 JNU_Notify(JNIEnv *env, jobject object)
991 {
992     if (object == NULL) {
993         JNU_ThrowNullPointerException(env, "JNU_Notify argument");
994         return;
995     }
996     if (Object_notifyMID == NULL) {
997         jclass cls = JNU_ClassObject(env);
998         if (cls == NULL) {
999             return;
1000         }
1001         Object_notifyMID = (*env)->GetMethodID(env, cls, "notify", "()V");
1002         if (Object_notifyMID == NULL) {
1003             return;
1004         }
1005     }
1006     (*env)->CallVoidMethod(env, object, Object_notifyMID);
1007 }
1008 
1009 JNIEXPORT void JNICALL
JNU_NotifyAll(JNIEnv * env,jobject object)1010 JNU_NotifyAll(JNIEnv *env, jobject object)
1011 {
1012     if (object == NULL) {
1013         JNU_ThrowNullPointerException(env, "JNU_NotifyAll argument");
1014         return;
1015     }
1016     if (Object_notifyAllMID == NULL) {
1017         jclass cls = JNU_ClassObject(env);
1018         if (cls == NULL) {
1019             return;
1020         }
1021         Object_notifyAllMID = (*env)->GetMethodID(env, cls,"notifyAll", "()V");
1022         if (Object_notifyAllMID == NULL) {
1023             return;
1024         }
1025     }
1026     (*env)->CallVoidMethod(env, object, Object_notifyAllMID);
1027 }
1028 
1029 
1030 /************************************************************************
1031  * Debugging utilities
1032  */
1033 
1034 JNIEXPORT void JNICALL
JNU_PrintString(JNIEnv * env,char * hdr,jstring string)1035 JNU_PrintString(JNIEnv *env, char *hdr, jstring string)
1036 {
1037     if (string == NULL) {
1038         fprintf(stderr, "%s: is NULL\n", hdr);
1039     } else {
1040         const char *stringPtr = JNU_GetStringPlatformChars(env, string, 0);
1041         if (stringPtr == 0)
1042             return;
1043         fprintf(stderr, "%s: %s\n", hdr, stringPtr);
1044         JNU_ReleaseStringPlatformChars(env, string, stringPtr);
1045     }
1046 }
1047 
1048 JNIEXPORT void JNICALL
JNU_PrintClass(JNIEnv * env,char * hdr,jobject object)1049 JNU_PrintClass(JNIEnv *env, char* hdr, jobject object)
1050 {
1051     if (object == NULL) {
1052         fprintf(stderr, "%s: object is NULL\n", hdr);
1053         return;
1054     } else {
1055         jclass cls = (*env)->GetObjectClass(env, object);
1056         jstring clsName = JNU_ToString(env, cls);
1057         JNU_PrintString(env, hdr, clsName);
1058         (*env)->DeleteLocalRef(env, cls);
1059         (*env)->DeleteLocalRef(env, clsName);
1060     }
1061 }
1062 
1063 JNIEXPORT jstring JNICALL
JNU_ToString(JNIEnv * env,jobject object)1064 JNU_ToString(JNIEnv *env, jobject object)
1065 {
1066     if (object == NULL) {
1067         return (*env)->NewStringUTF(env, "NULL");
1068     } else {
1069         return (jstring)JNU_CallMethodByName(env,
1070                                              NULL,
1071                                              object,
1072                                              "toString",
1073                                              "()Ljava/lang/String;").l;
1074     }
1075 }
1076 
1077 JNIEXPORT jvalue JNICALL
JNU_GetFieldByName(JNIEnv * env,jboolean * hasException,jobject obj,const char * name,const char * signature)1078 JNU_GetFieldByName(JNIEnv *env,
1079                    jboolean *hasException,
1080                    jobject obj,
1081                    const char *name,
1082                    const char *signature)
1083 {
1084     jclass cls;
1085     jfieldID fid;
1086     jvalue result;
1087 
1088     result.i = 0;
1089 
1090     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1091         goto done2;
1092 
1093     cls = (*env)->GetObjectClass(env, obj);
1094     fid = (*env)->GetFieldID(env, cls, name, signature);
1095     if (fid == 0)
1096         goto done1;
1097 
1098     switch (*signature) {
1099     case '[':
1100     case 'L':
1101         result.l = (*env)->GetObjectField(env, obj, fid);
1102         break;
1103     case 'Z':
1104         result.z = (*env)->GetBooleanField(env, obj, fid);
1105         break;
1106     case 'B':
1107         result.b = (*env)->GetByteField(env, obj, fid);
1108         break;
1109     case 'C':
1110         result.c = (*env)->GetCharField(env, obj, fid);
1111         break;
1112     case 'S':
1113         result.s = (*env)->GetShortField(env, obj, fid);
1114         break;
1115     case 'I':
1116         result.i = (*env)->GetIntField(env, obj, fid);
1117         break;
1118     case 'J':
1119         result.j = (*env)->GetLongField(env, obj, fid);
1120         break;
1121     case 'F':
1122         result.f = (*env)->GetFloatField(env, obj, fid);
1123         break;
1124     case 'D':
1125         result.d = (*env)->GetDoubleField(env, obj, fid);
1126         break;
1127 
1128     default:
1129         (*env)->FatalError(env, "JNU_GetFieldByName: illegal signature");
1130     }
1131 
1132  done1:
1133     (*env)->DeleteLocalRef(env, cls);
1134  done2:
1135     if (hasException) {
1136         *hasException = (*env)->ExceptionCheck(env);
1137     }
1138     return result;
1139 }
1140 
1141 JNIEXPORT void JNICALL
JNU_SetFieldByName(JNIEnv * env,jboolean * hasException,jobject obj,const char * name,const char * signature,...)1142 JNU_SetFieldByName(JNIEnv *env,
1143                    jboolean *hasException,
1144                    jobject obj,
1145                    const char *name,
1146                    const char *signature,
1147                    ...)
1148 {
1149     jclass cls;
1150     jfieldID fid;
1151     va_list args;
1152 
1153     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1154         goto done2;
1155 
1156     cls = (*env)->GetObjectClass(env, obj);
1157     fid = (*env)->GetFieldID(env, cls, name, signature);
1158     if (fid == 0)
1159         goto done1;
1160 
1161     va_start(args, signature);
1162     switch (*signature) {
1163     case '[':
1164     case 'L':
1165         (*env)->SetObjectField(env, obj, fid, va_arg(args, jobject));
1166         break;
1167     case 'Z':
1168         (*env)->SetBooleanField(env, obj, fid, (jboolean)va_arg(args, int));
1169         break;
1170     case 'B':
1171         (*env)->SetByteField(env, obj, fid, (jbyte)va_arg(args, int));
1172         break;
1173     case 'C':
1174         (*env)->SetCharField(env, obj, fid, (jchar)va_arg(args, int));
1175         break;
1176     case 'S':
1177         (*env)->SetShortField(env, obj, fid, (jshort)va_arg(args, int));
1178         break;
1179     case 'I':
1180         (*env)->SetIntField(env, obj, fid, va_arg(args, jint));
1181         break;
1182     case 'J':
1183         (*env)->SetLongField(env, obj, fid, va_arg(args, jlong));
1184         break;
1185     case 'F':
1186         (*env)->SetFloatField(env, obj, fid, (jfloat)va_arg(args, jdouble));
1187         break;
1188     case 'D':
1189         (*env)->SetDoubleField(env, obj, fid, va_arg(args, jdouble));
1190         break;
1191 
1192     default:
1193         (*env)->FatalError(env, "JNU_SetFieldByName: illegal signature");
1194     }
1195     va_end(args);
1196 
1197  done1:
1198     (*env)->DeleteLocalRef(env, cls);
1199  done2:
1200     if (hasException) {
1201         *hasException = (*env)->ExceptionCheck(env);
1202     }
1203 }
1204 
1205 JNIEXPORT jvalue JNICALL
JNU_GetStaticFieldByName(JNIEnv * env,jboolean * hasException,const char * classname,const char * name,const char * signature)1206 JNU_GetStaticFieldByName(JNIEnv *env,
1207                          jboolean *hasException,
1208                          const char *classname,
1209                          const char *name,
1210                          const char *signature)
1211 {
1212     jclass cls;
1213     jfieldID fid;
1214     jvalue result;
1215 
1216     result.i = 0;
1217 
1218     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1219         goto done2;
1220 
1221     cls = (*env)->FindClass(env, classname);
1222     if (cls == 0)
1223         goto done2;
1224 
1225     fid = (*env)->GetStaticFieldID(env, cls, name, signature);
1226     if (fid == 0)
1227         goto done1;
1228 
1229     switch (*signature) {
1230     case '[':
1231     case 'L':
1232         result.l = (*env)->GetStaticObjectField(env, cls, fid);
1233         break;
1234     case 'Z':
1235         result.z = (*env)->GetStaticBooleanField(env, cls, fid);
1236         break;
1237     case 'B':
1238         result.b = (*env)->GetStaticByteField(env, cls, fid);
1239         break;
1240     case 'C':
1241         result.c = (*env)->GetStaticCharField(env, cls, fid);
1242         break;
1243     case 'S':
1244         result.s = (*env)->GetStaticShortField(env, cls, fid);
1245         break;
1246     case 'I':
1247         result.i = (*env)->GetStaticIntField(env, cls, fid);
1248         break;
1249     case 'J':
1250         result.j = (*env)->GetStaticLongField(env, cls, fid);
1251         break;
1252     case 'F':
1253         result.f = (*env)->GetStaticFloatField(env, cls, fid);
1254         break;
1255     case 'D':
1256         result.d = (*env)->GetStaticDoubleField(env, cls, fid);
1257         break;
1258 
1259     default:
1260         (*env)->FatalError(env, "JNU_GetStaticFieldByName: illegal signature");
1261     }
1262 
1263  done1:
1264     (*env)->DeleteLocalRef(env, cls);
1265  done2:
1266     if (hasException) {
1267         *hasException = (*env)->ExceptionCheck(env);
1268     }
1269     return result;
1270 }
1271 
1272 JNIEXPORT void JNICALL
JNU_SetStaticFieldByName(JNIEnv * env,jboolean * hasException,const char * classname,const char * name,const char * signature,...)1273 JNU_SetStaticFieldByName(JNIEnv *env,
1274                          jboolean *hasException,
1275                          const char *classname,
1276                          const char *name,
1277                          const char *signature,
1278                          ...)
1279 {
1280     jclass cls;
1281     jfieldID fid;
1282     va_list args;
1283 
1284     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
1285         goto done2;
1286 
1287     cls = (*env)->FindClass(env, classname);
1288     if (cls == 0)
1289         goto done2;
1290 
1291     fid = (*env)->GetStaticFieldID(env, cls, name, signature);
1292     if (fid == 0)
1293         goto done1;
1294 
1295     va_start(args, signature);
1296     switch (*signature) {
1297     case '[':
1298     case 'L':
1299         (*env)->SetStaticObjectField(env, cls, fid, va_arg(args, jobject));
1300         break;
1301     case 'Z':
1302         (*env)->SetStaticBooleanField(env, cls, fid, (jboolean)va_arg(args, int));
1303         break;
1304     case 'B':
1305         (*env)->SetStaticByteField(env, cls, fid, (jbyte)va_arg(args, int));
1306         break;
1307     case 'C':
1308         (*env)->SetStaticCharField(env, cls, fid, (jchar)va_arg(args, int));
1309         break;
1310     case 'S':
1311         (*env)->SetStaticShortField(env, cls, fid, (jshort)va_arg(args, int));
1312         break;
1313     case 'I':
1314         (*env)->SetStaticIntField(env, cls, fid, va_arg(args, jint));
1315         break;
1316     case 'J':
1317         (*env)->SetStaticLongField(env, cls, fid, va_arg(args, jlong));
1318         break;
1319     case 'F':
1320         (*env)->SetStaticFloatField(env, cls, fid, (jfloat)va_arg(args, jdouble));
1321         break;
1322     case 'D':
1323         (*env)->SetStaticDoubleField(env, cls, fid, va_arg(args, jdouble));
1324         break;
1325 
1326     default:
1327         (*env)->FatalError(env, "JNU_SetStaticFieldByName: illegal signature");
1328     }
1329     va_end(args);
1330 
1331  done1:
1332     (*env)->DeleteLocalRef(env, cls);
1333  done2:
1334     if (hasException) {
1335         *hasException = (*env)->ExceptionCheck(env);
1336     }
1337 }
1338