Home | History | Annotate | Download | only in native
      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
     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
     56 JNU_ThrowNullPointerException(JNIEnv *env, const char *msg)
     57 {
     58     JNU_ThrowByName(env, "java/lang/NullPointerException", msg);
     59 }
     60 
     61 JNIEXPORT void JNICALL
     62 JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg)
     63 {
     64     JNU_ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", msg);
     65 }
     66 
     67 JNIEXPORT void JNICALL
     68 JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg)
     69 {
     70     JNU_ThrowByName(env, "java/lang/OutOfMemoryError", msg);
     71 }
     72 
     73 JNIEXPORT void JNICALL
     74 JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg)
     75 {
     76     JNU_ThrowByName(env, "java/lang/IllegalArgumentException", msg);
     77 }
     78 
     79 JNIEXPORT void JNICALL
     80 JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg)
     81 {
     82     JNU_ThrowByName(env, "java/lang/IllegalAccessError", msg);
     83 }
     84 
     85 JNIEXPORT void JNICALL
     86 JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg)
     87 {
     88     JNU_ThrowByName(env, "java/lang/IllegalAccessException", msg);
     89 }
     90 
     91 JNIEXPORT void JNICALL
     92 JNU_ThrowInternalError(JNIEnv *env, const char *msg)
     93 {
     94     JNU_ThrowByName(env, "java/lang/InternalError", msg);
     95 }
     96 
     97 JNIEXPORT void JNICALL
     98 JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg)
     99 {
    100     JNU_ThrowByName(env, "java/lang/NoSuchFieldException", msg);
    101 }
    102 
    103 JNIEXPORT void JNICALL
    104 JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg)
    105 {
    106     JNU_ThrowByName(env, "java/lang/NoSuchMethodException", msg);
    107 }
    108 
    109 JNIEXPORT void JNICALL
    110 JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg)
    111 {
    112     JNU_ThrowByName(env, "java/lang/ClassNotFoundException", msg);
    113 }
    114 
    115 JNIEXPORT void JNICALL
    116 JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg)
    117 {
    118     JNU_ThrowByName(env, "java/lang/NumberFormatException", msg);
    119 }
    120 
    121 JNIEXPORT void JNICALL
    122 JNU_ThrowIOException(JNIEnv *env, const char *msg)
    123 {
    124     JNU_ThrowByName(env, "java/io/IOException", msg);
    125 }
    126 
    127 JNIEXPORT void JNICALL
    128 JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg)
    129 {
    130     JNU_ThrowByName(env, "java/lang/NoSuchFieldError", msg);
    131 }
    132 
    133 JNIEXPORT void JNICALL
    134 JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg)
    135 {
    136     JNU_ThrowByName(env, "java/lang/NoSuchMethodError", msg);
    137 }
    138 
    139 JNIEXPORT void JNICALL
    140 JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg)
    141 {
    142     JNU_ThrowByName(env, "java/lang/StringIndexOutOfBoundsException", msg);
    143 }
    144 
    145 JNIEXPORT void JNICALL
    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
    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
    183 JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail)
    184 {
    185     JNU_ThrowByNameWithLastError(env, "java/io/IOException", defaultDetail);
    186 }
    187 
    188 
    189 JNIEXPORT jvalue JNICALL
    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
    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
    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
    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
    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 *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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