1 /* 2 * Copyright (c) 1997, 2018, 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 29 #include "jvm.h" 30 #include "jni.h" 31 #include "jni_util.h" 32 #include "java_lang_String.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 * getLastErrorString 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 size_t n = 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 179 JNIEXPORT void JNICALL 180 JNU_ThrowByNameWithTwoMessagesAndLastError 181 (JNIEnv *env, const char *name, const char *message1, const char *message2) 182 { 183 /* maybe we need to cache errno ? */ 184 size_t messagelen1 = message1 == NULL ? 0 : strlen(message1); 185 size_t messagelen2 = message2 == NULL ? 0 : strlen(message2); 186 size_t messageconclen = messagelen1 + messagelen2 + 3; 187 char *strl = (char *)malloc(messageconclen * sizeof(char)); 188 if (strl == 0) { 189 JNU_ThrowOutOfMemoryError(env, 0); 190 return; 191 } 192 jio_snprintf(strl, messageconclen, "%s:%s", message1, message2); 193 JNU_ThrowByNameWithMessageAndLastError(env, name, strl); 194 free(strl); 195 } 196 197 /* 198 * Throw an exception by name, using a given message and the string 199 * returned by getLastErrorString to construct the detail string. 200 */ 201 JNIEXPORT void JNICALL 202 JNU_ThrowByNameWithMessageAndLastError 203 (JNIEnv *env, const char *name, const char *message) 204 { 205 char buf[256]; 206 size_t n = getLastErrorString(buf, sizeof(buf)); 207 size_t messagelen = message == NULL ? 0 : strlen(message); 208 209 if (n > 0) { 210 jstring s = JNU_NewStringPlatform(env, buf); 211 if (s != NULL) { 212 jobject x = NULL; 213 if (messagelen) { 214 jstring s2 = NULL; 215 size_t messageextlen = messagelen + 4; 216 char *str1 = (char *)malloc((messageextlen) * sizeof(char)); 217 if (str1 == 0) { 218 JNU_ThrowOutOfMemoryError(env, 0); 219 return; 220 } 221 jio_snprintf(str1, messageextlen, " (%s)", message); 222 s2 = (*env)->NewStringUTF(env, str1); 223 free(str1); 224 JNU_CHECK_EXCEPTION(env); 225 if (s2 != NULL) { 226 jstring s3 = JNU_CallMethodByName( 227 env, NULL, s, "concat", 228 "(Ljava/lang/String;)Ljava/lang/String;", 229 s2).l; 230 (*env)->DeleteLocalRef(env, s2); 231 JNU_CHECK_EXCEPTION(env); 232 if (s3 != NULL) { 233 (*env)->DeleteLocalRef(env, s); 234 s = s3; 235 } 236 } 237 } 238 x = JNU_NewObjectByName(env, name, "(Ljava/lang/String;)V", s); 239 if (x != NULL) { 240 (*env)->Throw(env, x); 241 } 242 } 243 } 244 245 if (!(*env)->ExceptionOccurred(env)) { 246 if (messagelen) { 247 JNU_ThrowByName(env, name, message); 248 } else { 249 JNU_ThrowByName(env, name, "no further information"); 250 } 251 } 252 } 253 254 /* 255 * Convenience method. 256 * Call JNU_ThrowByNameWithLastError for java.io.IOException. 257 */ 258 JNIEXPORT void JNICALL 259 JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail) 260 { 261 JNU_ThrowByNameWithLastError(env, "java/io/IOException", defaultDetail); 262 } 263 264 265 JNIEXPORT jvalue JNICALL 266 JNU_CallStaticMethodByName(JNIEnv *env, 267 jboolean *hasException, 268 const char *class_name, 269 const char *name, 270 const char *signature, 271 ...) 272 { 273 jclass clazz; 274 jmethodID mid; 275 va_list args; 276 jvalue result; 277 const char *p = signature; 278 279 /* find out the return type */ 280 while (*p && *p != ')') 281 p++; 282 p++; 283 284 result.i = 0; 285 286 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 287 goto done2; 288 289 clazz = (*env)->FindClass(env, class_name); 290 if (clazz == 0) 291 goto done2; 292 mid = (*env)->GetStaticMethodID(env, clazz, name, signature); 293 if (mid == 0) 294 goto done1; 295 va_start(args, signature); 296 switch (*p) { 297 case 'V': 298 (*env)->CallStaticVoidMethodV(env, clazz, mid, args); 299 break; 300 case '[': 301 case 'L': 302 result.l = (*env)->CallStaticObjectMethodV(env, clazz, mid, args); 303 break; 304 case 'Z': 305 result.z = (*env)->CallStaticBooleanMethodV(env, clazz, mid, args); 306 break; 307 case 'B': 308 result.b = (*env)->CallStaticByteMethodV(env, clazz, mid, args); 309 break; 310 case 'C': 311 result.c = (*env)->CallStaticCharMethodV(env, clazz, mid, args); 312 break; 313 case 'S': 314 result.s = (*env)->CallStaticShortMethodV(env, clazz, mid, args); 315 break; 316 case 'I': 317 result.i = (*env)->CallStaticIntMethodV(env, clazz, mid, args); 318 break; 319 case 'J': 320 result.j = (*env)->CallStaticLongMethodV(env, clazz, mid, args); 321 break; 322 case 'F': 323 result.f = (*env)->CallStaticFloatMethodV(env, clazz, mid, args); 324 break; 325 case 'D': 326 result.d = (*env)->CallStaticDoubleMethodV(env, clazz, mid, args); 327 break; 328 default: 329 (*env)->FatalError(env, "JNU_CallStaticMethodByName: illegal signature"); 330 } 331 va_end(args); 332 333 done1: 334 (*env)->DeleteLocalRef(env, clazz); 335 done2: 336 if (hasException) { 337 *hasException = (*env)->ExceptionCheck(env); 338 } 339 return result; 340 } 341 342 JNIEXPORT jvalue JNICALL 343 JNU_CallMethodByName(JNIEnv *env, 344 jboolean *hasException, 345 jobject obj, 346 const char *name, 347 const char *signature, 348 ...) 349 { 350 jvalue result; 351 va_list args; 352 353 va_start(args, signature); 354 result = JNU_CallMethodByNameV(env, hasException, obj, name, signature, 355 args); 356 va_end(args); 357 358 return result; 359 } 360 361 362 JNIEXPORT jvalue JNICALL 363 JNU_CallMethodByNameV(JNIEnv *env, 364 jboolean *hasException, 365 jobject obj, 366 const char *name, 367 const char *signature, 368 va_list args) 369 { 370 jclass clazz; 371 jmethodID mid; 372 jvalue result; 373 const char *p = signature; 374 375 /* find out the return type */ 376 while (*p && *p != ')') 377 p++; 378 p++; 379 380 result.i = 0; 381 382 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 383 goto done2; 384 385 clazz = (*env)->GetObjectClass(env, obj); 386 mid = (*env)->GetMethodID(env, clazz, name, signature); 387 if (mid == 0) 388 goto done1; 389 390 switch (*p) { 391 case 'V': 392 (*env)->CallVoidMethodV(env, obj, mid, args); 393 break; 394 case '[': 395 case 'L': 396 result.l = (*env)->CallObjectMethodV(env, obj, mid, args); 397 break; 398 case 'Z': 399 result.z = (*env)->CallBooleanMethodV(env, obj, mid, args); 400 break; 401 case 'B': 402 result.b = (*env)->CallByteMethodV(env, obj, mid, args); 403 break; 404 case 'C': 405 result.c = (*env)->CallCharMethodV(env, obj, mid, args); 406 break; 407 case 'S': 408 result.s = (*env)->CallShortMethodV(env, obj, mid, args); 409 break; 410 case 'I': 411 result.i = (*env)->CallIntMethodV(env, obj, mid, args); 412 break; 413 case 'J': 414 result.j = (*env)->CallLongMethodV(env, obj, mid, args); 415 break; 416 case 'F': 417 result.f = (*env)->CallFloatMethodV(env, obj, mid, args); 418 break; 419 case 'D': 420 result.d = (*env)->CallDoubleMethodV(env, obj, mid, args); 421 break; 422 default: 423 (*env)->FatalError(env, "JNU_CallMethodByNameV: illegal signature"); 424 } 425 done1: 426 (*env)->DeleteLocalRef(env, clazz); 427 done2: 428 if (hasException) { 429 *hasException = (*env)->ExceptionCheck(env); 430 } 431 return result; 432 } 433 434 JNIEXPORT jobject JNICALL 435 JNU_NewObjectByName(JNIEnv *env, const char *class_name, 436 const char *constructor_sig, ...) 437 { 438 jobject obj = NULL; 439 440 jclass cls = 0; 441 jmethodID cls_initMID; 442 va_list args; 443 444 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 445 goto done; 446 447 cls = (*env)->FindClass(env, class_name); 448 if (cls == 0) { 449 goto done; 450 } 451 cls_initMID = (*env)->GetMethodID(env, cls, 452 "<init>", constructor_sig); 453 if (cls_initMID == NULL) { 454 goto done; 455 } 456 va_start(args, constructor_sig); 457 obj = (*env)->NewObjectV(env, cls, cls_initMID, args); 458 va_end(args); 459 460 done: 461 (*env)->DeleteLocalRef(env, cls); 462 return obj; 463 } 464 465 /* Optimized for charset ISO_8559_1 */ 466 static jstring 467 newSizedString8859_1(JNIEnv *env, const char *str, const int len) 468 { 469 jchar buf[512]; 470 jchar *str1; 471 jstring result; 472 int i; 473 474 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 475 return NULL; 476 477 if (len > 512) { 478 str1 = (jchar *)malloc(len * sizeof(jchar)); 479 if (str1 == 0) { 480 JNU_ThrowOutOfMemoryError(env, 0); 481 return 0; 482 } 483 } else 484 str1 = buf; 485 486 for (i=0;i<len;i++) 487 str1[i] = (unsigned char)str[i]; 488 result = (*env)->NewString(env, str1, len); 489 if (str1 != buf) 490 free(str1); 491 return result; 492 } 493 494 static jstring 495 newString8859_1(JNIEnv *env, const char *str) 496 { 497 int len = (int)strlen(str); 498 return newSizedString8859_1(env, str, len); 499 } 500 501 static const char* 502 getString8859_1Chars(JNIEnv *env, jstring jstr) 503 { 504 int i; 505 char *result; 506 jint len = (*env)->GetStringLength(env, jstr); 507 const jchar *str = (*env)->GetStringCritical(env, jstr, 0); 508 if (str == 0) { 509 return 0; 510 } 511 512 result = MALLOC_MIN4(len); 513 if (result == 0) { 514 (*env)->ReleaseStringCritical(env, jstr, str); 515 JNU_ThrowOutOfMemoryError(env, 0); 516 return 0; 517 } 518 519 for (i=0; i<len; i++) { 520 jchar unicode = str[i]; 521 if (unicode <= 0x00ff) 522 result[i] = (char)unicode; 523 else 524 result[i] = '?'; 525 } 526 527 result[len] = 0; 528 (*env)->ReleaseStringCritical(env, jstr, str); 529 return result; 530 } 531 532 533 /* Optimized for charset ISO646-US (us-ascii) */ 534 static jstring 535 newString646_US(JNIEnv *env, const char *str) 536 { 537 int len = (int)strlen(str); 538 jchar buf[512]; 539 jchar *str1; 540 jstring result; 541 int i; 542 543 if (len > 512) { 544 str1 = (jchar *)malloc(len * sizeof(jchar)); 545 if (str1 == 0) { 546 JNU_ThrowOutOfMemoryError(env, 0); 547 return 0; 548 } 549 } else 550 str1 = buf; 551 552 for (i=0; i<len; i++) { 553 unsigned char c = (unsigned char)str[i]; 554 if (c <= 0x7f) 555 str1[i] = c; 556 else 557 str1[i] = '?'; 558 } 559 560 result = (*env)->NewString(env, str1, len); 561 if (str1 != buf) 562 free(str1); 563 return result; 564 } 565 566 static const char* 567 getString646_USChars(JNIEnv *env, jstring jstr) 568 { 569 int i; 570 char *result; 571 jint len = (*env)->GetStringLength(env, jstr); 572 const jchar *str = (*env)->GetStringCritical(env, jstr, 0); 573 if (str == 0) { 574 return 0; 575 } 576 577 result = MALLOC_MIN4(len); 578 if (result == 0) { 579 (*env)->ReleaseStringCritical(env, jstr, str); 580 JNU_ThrowOutOfMemoryError(env, 0); 581 return 0; 582 } 583 584 for (i=0; i<len; i++) { 585 jchar unicode = str[i]; 586 if (unicode <= 0x007f ) 587 result[i] = (char)unicode; 588 else 589 result[i] = '?'; 590 } 591 592 result[len] = 0; 593 (*env)->ReleaseStringCritical(env, jstr, str); 594 return result; 595 } 596 597 /* enumeration of c1 row from Cp1252 */ 598 static int cp1252c1chars[32] = { 599 0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021, 600 0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD, 601 0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014, 602 0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178 603 }; 604 605 /* Optimized for charset Cp1252 */ 606 static jstring 607 newStringCp1252(JNIEnv *env, const char *str) 608 { 609 int len = (int) strlen(str); 610 jchar buf[512]; 611 jchar *str1; 612 jstring result; 613 int i; 614 615 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 616 return NULL; 617 618 if (len > 512) { 619 str1 = (jchar *)malloc(len * sizeof(jchar)); 620 if (str1 == 0) { 621 JNU_ThrowOutOfMemoryError(env, 0); 622 return 0; 623 } 624 } else 625 str1 = buf; 626 627 for (i=0; i<len; i++) { 628 unsigned char c = (unsigned char)str[i]; 629 if ((c >= 0x80) && (c <= 0x9f)) 630 str1[i] = cp1252c1chars[c-128]; 631 else 632 str1[i] = c; 633 } 634 635 result = (*env)->NewString(env, str1, len); 636 if (str1 != buf) 637 free(str1); 638 return result; 639 } 640 641 static const char* 642 getStringCp1252Chars(JNIEnv *env, jstring jstr) 643 { 644 int i; 645 char *result; 646 jint len = (*env)->GetStringLength(env, jstr); 647 const jchar *str = (*env)->GetStringCritical(env, jstr, 0); 648 if (str == 0) { 649 return 0; 650 } 651 652 result = MALLOC_MIN4(len); 653 if (result == 0) { 654 (*env)->ReleaseStringCritical(env, jstr, str); 655 JNU_ThrowOutOfMemoryError(env, 0); 656 return 0; 657 } 658 659 for (i=0; i<len; i++) { 660 jchar c = str[i]; 661 if (c < 256) { 662 if ((c >= 0x80) && (c <= 0x9f)) { 663 result[i] = '?'; 664 } else { 665 result[i] = (char)c; 666 } 667 } else switch(c) { 668 case 0x20AC: result[i] = (char)0x80; break; 669 case 0x201A: result[i] = (char)0x82; break; 670 case 0x0192: result[i] = (char)0x83; break; 671 case 0x201E: result[i] = (char)0x84; break; 672 case 0x2026: result[i] = (char)0x85; break; 673 case 0x2020: result[i] = (char)0x86; break; 674 case 0x2021: result[i] = (char)0x87; break; 675 case 0x02C6: result[i] = (char)0x88; break; 676 case 0x2030: result[i] = (char)0x89; break; 677 case 0x0160: result[i] = (char)0x8A; break; 678 case 0x2039: result[i] = (char)0x8B; break; 679 case 0x0152: result[i] = (char)0x8C; break; 680 case 0x017D: result[i] = (char)0x8E; break; 681 case 0x2018: result[i] = (char)0x91; break; 682 case 0x2019: result[i] = (char)0x92; break; 683 case 0x201C: result[i] = (char)0x93; break; 684 case 0x201D: result[i] = (char)0x94; break; 685 case 0x2022: result[i] = (char)0x95; break; 686 case 0x2013: result[i] = (char)0x96; break; 687 case 0x2014: result[i] = (char)0x97; break; 688 case 0x02DC: result[i] = (char)0x98; break; 689 case 0x2122: result[i] = (char)0x99; break; 690 case 0x0161: result[i] = (char)0x9A; break; 691 case 0x203A: result[i] = (char)0x9B; break; 692 case 0x0153: result[i] = (char)0x9C; break; 693 case 0x017E: result[i] = (char)0x9E; break; 694 case 0x0178: result[i] = (char)0x9F; break; 695 default: result[i] = '?'; break; 696 } 697 } 698 699 result[len] = 0; 700 (*env)->ReleaseStringCritical(env, jstr, str); 701 return result; 702 } 703 704 static int fastEncoding = NO_ENCODING_YET; 705 static jstring jnuEncoding = NULL; 706 707 /* Cached method IDs */ 708 static jmethodID String_init_ID; /* String(byte[], enc) */ 709 static jmethodID String_getBytes_ID; /* String.getBytes(enc) */ 710 711 /* Cached field IDs */ 712 static jfieldID String_coder_ID; /* String.coder */ 713 static jfieldID String_value_ID; /* String.value */ 714 715 static jboolean isJNUEncodingSupported = JNI_FALSE; 716 static jboolean jnuEncodingSupported(JNIEnv *env) { 717 jboolean exe; 718 if (isJNUEncodingSupported == JNI_TRUE) { 719 return JNI_TRUE; 720 } 721 isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName ( 722 env, &exe, 723 "java/nio/charset/Charset", 724 "isSupported", 725 "(Ljava/lang/String;)Z", 726 jnuEncoding).z; 727 return isJNUEncodingSupported; 728 } 729 730 /* Create a new string by converting str to a heap-allocated byte array and 731 * calling the appropriate String constructor. 732 */ 733 static jstring 734 newSizedStringJava(JNIEnv *env, const char *str, const int len) 735 { 736 jstring result = NULL; 737 jbyteArray bytes = 0; 738 739 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 740 return NULL; 741 742 bytes = (*env)->NewByteArray(env, len); 743 if (bytes != NULL) { 744 jclass strClazz = JNU_ClassString(env); 745 CHECK_NULL_RETURN(strClazz, 0); 746 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str); 747 if (jnuEncodingSupported(env)) { 748 result = (*env)->NewObject(env, strClazz, 749 String_init_ID, bytes, jnuEncoding); 750 } else { 751 /*If the encoding specified in sun.jnu.encoding is not endorsed 752 by "Charset.isSupported" we have to fall back to use String(byte[]) 753 explicitly here without specifying the encoding name, in which the 754 StringCoding class will pickup the iso-8859-1 as the fallback 755 converter for us. 756 */ 757 jmethodID mid = (*env)->GetMethodID(env, strClazz, 758 "<init>", "([B)V"); 759 if (mid != NULL) { 760 result = (*env)->NewObject(env, strClazz, mid, bytes); 761 } 762 } 763 (*env)->DeleteLocalRef(env, bytes); 764 return result; 765 } 766 return NULL; 767 } 768 769 static jstring 770 newStringJava(JNIEnv *env, const char *str) 771 { 772 int len = (int)strlen(str); 773 return newSizedStringJava(env, str, len); 774 } 775 776 /* Optimized for charset UTF-8 */ 777 static jstring 778 newStringUTF8(JNIEnv *env, const char *str) 779 { 780 int len; 781 const unsigned char *p; 782 unsigned char asciiCheck; 783 for (asciiCheck = 0, p = (const unsigned char*)str; *p != '\0'; p++) { 784 asciiCheck |= *p; 785 } 786 len = (int)((const char*)p - str); 787 788 if (asciiCheck < 0x80) { 789 // ascii fast-path 790 return newSizedString8859_1(env, str, len); 791 } 792 793 return newSizedStringJava(env, str, len); 794 } 795 796 /* Initialize the fast encoding from the encoding name. 797 * Export InitializeEncoding so that the VM can initialize it if required. 798 */ 799 JNIEXPORT void 800 InitializeEncoding(JNIEnv *env, const char *encname) 801 { 802 jclass strClazz = NULL; 803 804 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 805 return; 806 807 strClazz = JNU_ClassString(env); 808 CHECK_NULL(strClazz); 809 810 if (encname) { 811 /* 812 * On Solaris with nl_langinfo() called in GetJavaProperties(): 813 * 814 * locale undefined -> NULL -> hardcoded default 815 * "C" locale -> "" -> hardcoded default (on 2.6) 816 * "C" locale -> "ISO646-US" (on Sol 7/8) 817 * "en_US" locale -> "ISO8859-1" 818 * "en_GB" locale -> "ISO8859-1" (on Sol 7/8) 819 * "en_UK" locale -> "ISO8859-1" (on 2.6) 820 */ 821 if ((strcmp(encname, "8859_1") == 0) || 822 (strcmp(encname, "ISO8859-1") == 0) || 823 (strcmp(encname, "ISO8859_1") == 0) || 824 (strcmp(encname, "ISO-8859-1") == 0)) { 825 fastEncoding = FAST_8859_1; 826 } else if (strcmp(encname, "UTF-8") == 0) { 827 jstring enc = (*env)->NewStringUTF(env, encname); 828 if (enc == NULL) 829 return; 830 fastEncoding = FAST_UTF_8; 831 jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc); 832 (*env)->DeleteLocalRef(env, enc); 833 } else if (strcmp(encname, "ISO646-US") == 0) { 834 fastEncoding = FAST_646_US; 835 } else if (strcmp(encname, "Cp1252") == 0 || 836 /* This is a temporary fix until we move */ 837 /* to wide character versions of all Windows */ 838 /* calls. */ 839 strcmp(encname, "utf-16le") == 0) { 840 fastEncoding = FAST_CP1252; 841 } else { 842 jstring enc = (*env)->NewStringUTF(env, encname); 843 if (enc == NULL) 844 return; 845 fastEncoding = NO_FAST_ENCODING; 846 jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc); 847 (*env)->DeleteLocalRef(env, enc); 848 } 849 } else { 850 JNU_ThrowInternalError(env, "platform encoding undefined"); 851 return; 852 } 853 854 /* Initialize method-id cache */ 855 String_getBytes_ID = (*env)->GetMethodID(env, strClazz, 856 "getBytes", "(Ljava/lang/String;)[B"); 857 CHECK_NULL(String_getBytes_ID); 858 String_init_ID = (*env)->GetMethodID(env, strClazz, 859 "<init>", "([BLjava/lang/String;)V"); 860 CHECK_NULL(String_init_ID); 861 String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B"); 862 CHECK_NULL(String_coder_ID); 863 String_value_ID = (*env)->GetFieldID(env, strClazz, "value", "[B"); 864 CHECK_NULL(String_value_ID); 865 } 866 867 JNIEXPORT jstring 868 NewStringPlatform(JNIEnv *env, const char *str) 869 { 870 return JNU_NewStringPlatform(env, str); 871 } 872 873 JNIEXPORT jstring JNICALL 874 JNU_NewStringPlatform(JNIEnv *env, const char *str) 875 { 876 if (fastEncoding == FAST_UTF_8) 877 return newStringUTF8(env, str); 878 if (fastEncoding == FAST_8859_1) 879 return newString8859_1(env, str); 880 if (fastEncoding == FAST_646_US) 881 return newString646_US(env, str); 882 if (fastEncoding == FAST_CP1252) 883 return newStringCp1252(env, str); 884 if (fastEncoding == NO_ENCODING_YET) { 885 JNU_ThrowInternalError(env, "platform encoding not initialized"); 886 return NULL; 887 } 888 return newStringJava(env, str); 889 } 890 891 JNIEXPORT const char * 892 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 893 { 894 return JNU_GetStringPlatformChars(env, jstr, isCopy); 895 } 896 897 static const char* getStringBytes(JNIEnv *env, jstring jstr) { 898 char *result = NULL; 899 jbyteArray hab = 0; 900 901 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 902 return 0; 903 904 if (jnuEncodingSupported(env)) { 905 hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding); 906 } else { 907 jmethodID mid; 908 jclass strClazz = JNU_ClassString(env); 909 CHECK_NULL_RETURN(strClazz, 0); 910 mid = (*env)->GetMethodID(env, strClazz, 911 "getBytes", "()[B"); 912 if (mid != NULL) { 913 hab = (*env)->CallObjectMethod(env, jstr, mid); 914 } 915 } 916 917 if (!(*env)->ExceptionCheck(env)) { 918 jint len = (*env)->GetArrayLength(env, hab); 919 result = MALLOC_MIN4(len); 920 if (result == 0) { 921 JNU_ThrowOutOfMemoryError(env, 0); 922 (*env)->DeleteLocalRef(env, hab); 923 return 0; 924 } 925 (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result); 926 result[len] = 0; /* NULL-terminate */ 927 } 928 929 (*env)->DeleteLocalRef(env, hab); 930 return result; 931 } 932 933 static const char* 934 getStringUTF8(JNIEnv *env, jstring jstr) 935 { 936 int i; 937 char *result; 938 jbyteArray value; 939 jint len; 940 jbyte *str; 941 jint rlen; 942 int ri; 943 jbyte coder = (*env)->GetByteField(env, jstr, String_coder_ID); 944 if (coder != java_lang_String_LATIN1) { 945 return getStringBytes(env, jstr); 946 } 947 if ((*env)->EnsureLocalCapacity(env, 2) < 0) { 948 return NULL; 949 } 950 value = (*env)->GetObjectField(env, jstr, String_value_ID); 951 if (value == NULL) 952 return NULL; 953 len = (*env)->GetArrayLength(env, value); 954 str = (*env)->GetPrimitiveArrayCritical(env, value, NULL); 955 if (str == NULL) { 956 return NULL; 957 } 958 959 rlen = len; 960 // we need two bytes for each latin-1 char above 127 (negative jbytes) 961 for (i = 0; i < len; i++) { 962 if (str[i] < 0) { 963 rlen++; 964 } 965 } 966 967 result = MALLOC_MIN4(rlen); 968 if (result == NULL) { 969 (*env)->ReleasePrimitiveArrayCritical(env, value, str, 0); 970 JNU_ThrowOutOfMemoryError(env, 0); 971 return NULL; 972 } 973 974 for (ri = 0, i = 0; i < len; i++) { 975 jbyte c = str[i]; 976 if (c < 0) { 977 result[ri++] = (char)(0xc0 | ((c & 0xff) >> 6)); 978 result[ri++] = (char)(0x80 | (c & 0x3f)); 979 } else { 980 result[ri++] = c; 981 } 982 } 983 (*env)->ReleasePrimitiveArrayCritical(env, value, str, 0); 984 result[rlen] = '\0'; 985 return result; 986 } 987 988 JNIEXPORT const char * JNICALL 989 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 990 { 991 992 if (isCopy) 993 *isCopy = JNI_TRUE; 994 995 if (fastEncoding == FAST_UTF_8) 996 return getStringUTF8(env, jstr); 997 if (fastEncoding == FAST_8859_1) 998 return getString8859_1Chars(env, jstr); 999 if (fastEncoding == FAST_646_US) 1000 return getString646_USChars(env, jstr); 1001 if (fastEncoding == FAST_CP1252) 1002 return getStringCp1252Chars(env, jstr); 1003 if (fastEncoding == NO_ENCODING_YET) { 1004 JNU_ThrowInternalError(env, "platform encoding not initialized"); 1005 return 0; 1006 } else 1007 return getStringBytes(env, jstr); 1008 } 1009 1010 JNIEXPORT void JNICALL 1011 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str) 1012 { 1013 free((void *)str); 1014 } 1015 1016 /* 1017 * Export the platform dependent path canonicalization so that 1018 * VM can find it when loading system classes. 1019 * This function is also used by the instrumentation agent. 1020 */ 1021 extern int canonicalize(char *path, const char *out, int len); 1022 1023 JNIEXPORT int 1024 Canonicalize(JNIEnv *unused, char *orig, char *out, int len) 1025 { 1026 /* canonicalize an already natived path */ 1027 return canonicalize(orig, out, len); 1028 } 1029 1030 JNIEXPORT jclass JNICALL 1031 JNU_ClassString(JNIEnv *env) 1032 { 1033 static jclass cls = 0; 1034 if (cls == 0) { 1035 jclass c; 1036 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 1037 return 0; 1038 c = (*env)->FindClass(env, "java/lang/String"); 1039 CHECK_NULL_RETURN(c, NULL); 1040 cls = (*env)->NewGlobalRef(env, c); 1041 (*env)->DeleteLocalRef(env, c); 1042 } 1043 return cls; 1044 } 1045 1046 JNIEXPORT jclass JNICALL 1047 JNU_ClassClass(JNIEnv *env) 1048 { 1049 static jclass cls = 0; 1050 if (cls == 0) { 1051 jclass c; 1052 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 1053 return 0; 1054 c = (*env)->FindClass(env, "java/lang/Class"); 1055 CHECK_NULL_RETURN(c, NULL); 1056 cls = (*env)->NewGlobalRef(env, c); 1057 (*env)->DeleteLocalRef(env, c); 1058 } 1059 return cls; 1060 } 1061 1062 JNIEXPORT jclass JNICALL 1063 JNU_ClassObject(JNIEnv *env) 1064 { 1065 static jclass cls = 0; 1066 if (cls == 0) { 1067 jclass c; 1068 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 1069 return 0; 1070 c = (*env)->FindClass(env, "java/lang/Object"); 1071 CHECK_NULL_RETURN(c, NULL); 1072 cls = (*env)->NewGlobalRef(env, c); 1073 (*env)->DeleteLocalRef(env, c); 1074 } 1075 return cls; 1076 } 1077 1078 JNIEXPORT jclass JNICALL 1079 JNU_ClassThrowable(JNIEnv *env) 1080 { 1081 static jclass cls = 0; 1082 if (cls == 0) { 1083 jclass c; 1084 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 1085 return 0; 1086 c = (*env)->FindClass(env, "java/lang/Throwable"); 1087 CHECK_NULL_RETURN(c, NULL); 1088 cls = (*env)->NewGlobalRef(env, c); 1089 (*env)->DeleteLocalRef(env, c); 1090 } 1091 return cls; 1092 } 1093 1094 JNIEXPORT jint JNICALL 1095 JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, 1096 jint count) 1097 { 1098 int i; 1099 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 1100 return -1; 1101 for (i=0; i<count; i++) { 1102 jstring p = (*env)->GetObjectArrayElement(env, src, i); 1103 (*env)->SetObjectArrayElement(env, dst, i, p); 1104 (*env)->DeleteLocalRef(env, p); 1105 } 1106 return 0; 1107 } 1108 1109 JNIEXPORT void * JNICALL 1110 JNU_GetEnv(JavaVM *vm, jint version) 1111 { 1112 void *env; 1113 (*vm)->GetEnv(vm, &env, version); 1114 return env; 1115 } 1116 1117 JNIEXPORT jint JNICALL 1118 JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char* classname) 1119 { 1120 jclass cls; 1121 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 1122 return JNI_ERR; 1123 cls = (*env)->FindClass(env, classname); 1124 if (cls != NULL) { 1125 jint result = (*env)->IsInstanceOf(env, object, cls); 1126 (*env)->DeleteLocalRef(env, cls); 1127 return result; 1128 } 1129 return JNI_ERR; 1130 } 1131 1132 JNIEXPORT jboolean JNICALL 1133 JNU_Equals(JNIEnv *env, jobject object1, jobject object2) 1134 { 1135 static jmethodID mid = NULL; 1136 if (mid == NULL) { 1137 jclass objClazz = JNU_ClassObject(env); 1138 CHECK_NULL_RETURN(objClazz, JNI_FALSE); 1139 mid = (*env)->GetMethodID(env, objClazz, "equals", 1140 "(Ljava/lang/Object;)Z"); 1141 CHECK_NULL_RETURN(mid, JNI_FALSE); 1142 } 1143 return (*env)->CallBooleanMethod(env, object1, mid, object2); 1144 } 1145 1146 1147 /************************************************************************ 1148 * Thread calls 1149 */ 1150 1151 static jmethodID Object_waitMID; 1152 static jmethodID Object_notifyMID; 1153 static jmethodID Object_notifyAllMID; 1154 1155 JNIEXPORT void JNICALL 1156 JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout) 1157 { 1158 if (object == NULL) { 1159 JNU_ThrowNullPointerException(env, "JNU_MonitorWait argument"); 1160 return; 1161 } 1162 if (Object_waitMID == NULL) { 1163 jclass cls = JNU_ClassObject(env); 1164 if (cls == NULL) { 1165 return; 1166 } 1167 Object_waitMID = (*env)->GetMethodID(env, cls, "wait", "(J)V"); 1168 if (Object_waitMID == NULL) { 1169 return; 1170 } 1171 } 1172 (*env)->CallVoidMethod(env, object, Object_waitMID, timeout); 1173 } 1174 1175 JNIEXPORT void JNICALL 1176 JNU_Notify(JNIEnv *env, jobject object) 1177 { 1178 if (object == NULL) { 1179 JNU_ThrowNullPointerException(env, "JNU_Notify argument"); 1180 return; 1181 } 1182 if (Object_notifyMID == NULL) { 1183 jclass cls = JNU_ClassObject(env); 1184 if (cls == NULL) { 1185 return; 1186 } 1187 Object_notifyMID = (*env)->GetMethodID(env, cls, "notify", "()V"); 1188 if (Object_notifyMID == NULL) { 1189 return; 1190 } 1191 } 1192 (*env)->CallVoidMethod(env, object, Object_notifyMID); 1193 } 1194 1195 JNIEXPORT void JNICALL 1196 JNU_NotifyAll(JNIEnv *env, jobject object) 1197 { 1198 if (object == NULL) { 1199 JNU_ThrowNullPointerException(env, "JNU_NotifyAll argument"); 1200 return; 1201 } 1202 if (Object_notifyAllMID == NULL) { 1203 jclass cls = JNU_ClassObject(env); 1204 if (cls == NULL) { 1205 return; 1206 } 1207 Object_notifyAllMID = (*env)->GetMethodID(env, cls,"notifyAll", "()V"); 1208 if (Object_notifyAllMID == NULL) { 1209 return; 1210 } 1211 } 1212 (*env)->CallVoidMethod(env, object, Object_notifyAllMID); 1213 } 1214 1215 1216 /************************************************************************ 1217 * Debugging utilities 1218 */ 1219 1220 JNIEXPORT void JNICALL 1221 JNU_PrintString(JNIEnv *env, char *hdr, jstring string) 1222 { 1223 if (string == NULL) { 1224 fprintf(stderr, "%s: is NULL\n", hdr); 1225 } else { 1226 const char *stringPtr = JNU_GetStringPlatformChars(env, string, 0); 1227 if (stringPtr == 0) 1228 return; 1229 fprintf(stderr, "%s: %s\n", hdr, stringPtr); 1230 JNU_ReleaseStringPlatformChars(env, string, stringPtr); 1231 } 1232 } 1233 1234 JNIEXPORT void JNICALL 1235 JNU_PrintClass(JNIEnv *env, char* hdr, jobject object) 1236 { 1237 if (object == NULL) { 1238 fprintf(stderr, "%s: object is NULL\n", hdr); 1239 return; 1240 } else { 1241 jclass cls = (*env)->GetObjectClass(env, object); 1242 jstring clsName = JNU_ToString(env, cls); 1243 if (clsName == NULL) { 1244 JNU_PrintString(env, hdr, clsName); 1245 } 1246 (*env)->DeleteLocalRef(env, cls); 1247 (*env)->DeleteLocalRef(env, clsName); 1248 } 1249 } 1250 1251 JNIEXPORT jstring JNICALL 1252 JNU_ToString(JNIEnv *env, jobject object) 1253 { 1254 if (object == NULL) { 1255 return (*env)->NewStringUTF(env, "NULL"); 1256 } else { 1257 return (jstring)JNU_CallMethodByName(env, 1258 NULL, 1259 object, 1260 "toString", 1261 "()Ljava/lang/String;").l; 1262 } 1263 } 1264 1265 JNIEXPORT jvalue JNICALL 1266 JNU_GetFieldByName(JNIEnv *env, 1267 jboolean *hasException, 1268 jobject obj, 1269 const char *name, 1270 const char *signature) 1271 { 1272 jclass cls; 1273 jfieldID fid; 1274 jvalue result; 1275 1276 result.i = 0; 1277 1278 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1279 goto done2; 1280 1281 cls = (*env)->GetObjectClass(env, obj); 1282 fid = (*env)->GetFieldID(env, cls, name, signature); 1283 if (fid == 0) 1284 goto done1; 1285 1286 switch (*signature) { 1287 case '[': 1288 case 'L': 1289 result.l = (*env)->GetObjectField(env, obj, fid); 1290 break; 1291 case 'Z': 1292 result.z = (*env)->GetBooleanField(env, obj, fid); 1293 break; 1294 case 'B': 1295 result.b = (*env)->GetByteField(env, obj, fid); 1296 break; 1297 case 'C': 1298 result.c = (*env)->GetCharField(env, obj, fid); 1299 break; 1300 case 'S': 1301 result.s = (*env)->GetShortField(env, obj, fid); 1302 break; 1303 case 'I': 1304 result.i = (*env)->GetIntField(env, obj, fid); 1305 break; 1306 case 'J': 1307 result.j = (*env)->GetLongField(env, obj, fid); 1308 break; 1309 case 'F': 1310 result.f = (*env)->GetFloatField(env, obj, fid); 1311 break; 1312 case 'D': 1313 result.d = (*env)->GetDoubleField(env, obj, fid); 1314 break; 1315 1316 default: 1317 (*env)->FatalError(env, "JNU_GetFieldByName: illegal signature"); 1318 } 1319 1320 done1: 1321 (*env)->DeleteLocalRef(env, cls); 1322 done2: 1323 if (hasException) { 1324 *hasException = (*env)->ExceptionCheck(env); 1325 } 1326 return result; 1327 } 1328 1329 JNIEXPORT void JNICALL 1330 JNU_SetFieldByName(JNIEnv *env, 1331 jboolean *hasException, 1332 jobject obj, 1333 const char *name, 1334 const char *signature, 1335 ...) 1336 { 1337 jclass cls; 1338 jfieldID fid; 1339 va_list args; 1340 1341 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1342 goto done2; 1343 1344 cls = (*env)->GetObjectClass(env, obj); 1345 fid = (*env)->GetFieldID(env, cls, name, signature); 1346 if (fid == 0) 1347 goto done1; 1348 1349 va_start(args, signature); 1350 switch (*signature) { 1351 case '[': 1352 case 'L': 1353 (*env)->SetObjectField(env, obj, fid, va_arg(args, jobject)); 1354 break; 1355 case 'Z': 1356 (*env)->SetBooleanField(env, obj, fid, (jboolean)va_arg(args, int)); 1357 break; 1358 case 'B': 1359 (*env)->SetByteField(env, obj, fid, (jbyte)va_arg(args, int)); 1360 break; 1361 case 'C': 1362 (*env)->SetCharField(env, obj, fid, (jchar)va_arg(args, int)); 1363 break; 1364 case 'S': 1365 (*env)->SetShortField(env, obj, fid, (jshort)va_arg(args, int)); 1366 break; 1367 case 'I': 1368 (*env)->SetIntField(env, obj, fid, va_arg(args, jint)); 1369 break; 1370 case 'J': 1371 (*env)->SetLongField(env, obj, fid, va_arg(args, jlong)); 1372 break; 1373 case 'F': 1374 (*env)->SetFloatField(env, obj, fid, (jfloat)va_arg(args, jdouble)); 1375 break; 1376 case 'D': 1377 (*env)->SetDoubleField(env, obj, fid, va_arg(args, jdouble)); 1378 break; 1379 1380 default: 1381 (*env)->FatalError(env, "JNU_SetFieldByName: illegal signature"); 1382 } 1383 va_end(args); 1384 1385 done1: 1386 (*env)->DeleteLocalRef(env, cls); 1387 done2: 1388 if (hasException) { 1389 *hasException = (*env)->ExceptionCheck(env); 1390 } 1391 } 1392 1393 JNIEXPORT jvalue JNICALL 1394 JNU_GetStaticFieldByName(JNIEnv *env, 1395 jboolean *hasException, 1396 const char *classname, 1397 const char *name, 1398 const char *signature) 1399 { 1400 jclass cls; 1401 jfieldID fid; 1402 jvalue result; 1403 1404 result.i = 0; 1405 1406 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1407 goto done2; 1408 1409 cls = (*env)->FindClass(env, classname); 1410 if (cls == 0) 1411 goto done2; 1412 1413 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1414 if (fid == 0) 1415 goto done1; 1416 1417 switch (*signature) { 1418 case '[': 1419 case 'L': 1420 result.l = (*env)->GetStaticObjectField(env, cls, fid); 1421 break; 1422 case 'Z': 1423 result.z = (*env)->GetStaticBooleanField(env, cls, fid); 1424 break; 1425 case 'B': 1426 result.b = (*env)->GetStaticByteField(env, cls, fid); 1427 break; 1428 case 'C': 1429 result.c = (*env)->GetStaticCharField(env, cls, fid); 1430 break; 1431 case 'S': 1432 result.s = (*env)->GetStaticShortField(env, cls, fid); 1433 break; 1434 case 'I': 1435 result.i = (*env)->GetStaticIntField(env, cls, fid); 1436 break; 1437 case 'J': 1438 result.j = (*env)->GetStaticLongField(env, cls, fid); 1439 break; 1440 case 'F': 1441 result.f = (*env)->GetStaticFloatField(env, cls, fid); 1442 break; 1443 case 'D': 1444 result.d = (*env)->GetStaticDoubleField(env, cls, fid); 1445 break; 1446 1447 default: 1448 (*env)->FatalError(env, "JNU_GetStaticFieldByName: illegal signature"); 1449 } 1450 1451 done1: 1452 (*env)->DeleteLocalRef(env, cls); 1453 done2: 1454 if (hasException) { 1455 *hasException = (*env)->ExceptionCheck(env); 1456 } 1457 return result; 1458 } 1459 1460 JNIEXPORT void JNICALL 1461 JNU_SetStaticFieldByName(JNIEnv *env, 1462 jboolean *hasException, 1463 const char *classname, 1464 const char *name, 1465 const char *signature, 1466 ...) 1467 { 1468 jclass cls; 1469 jfieldID fid; 1470 va_list args; 1471 1472 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1473 goto done2; 1474 1475 cls = (*env)->FindClass(env, classname); 1476 if (cls == 0) 1477 goto done2; 1478 1479 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1480 if (fid == 0) 1481 goto done1; 1482 1483 va_start(args, signature); 1484 switch (*signature) { 1485 case '[': 1486 case 'L': 1487 (*env)->SetStaticObjectField(env, cls, fid, va_arg(args, jobject)); 1488 break; 1489 case 'Z': 1490 (*env)->SetStaticBooleanField(env, cls, fid, (jboolean)va_arg(args, int)); 1491 break; 1492 case 'B': 1493 (*env)->SetStaticByteField(env, cls, fid, (jbyte)va_arg(args, int)); 1494 break; 1495 case 'C': 1496 (*env)->SetStaticCharField(env, cls, fid, (jchar)va_arg(args, int)); 1497 break; 1498 case 'S': 1499 (*env)->SetStaticShortField(env, cls, fid, (jshort)va_arg(args, int)); 1500 break; 1501 case 'I': 1502 (*env)->SetStaticIntField(env, cls, fid, va_arg(args, jint)); 1503 break; 1504 case 'J': 1505 (*env)->SetStaticLongField(env, cls, fid, va_arg(args, jlong)); 1506 break; 1507 case 'F': 1508 (*env)->SetStaticFloatField(env, cls, fid, (jfloat)va_arg(args, jdouble)); 1509 break; 1510 case 'D': 1511 (*env)->SetStaticDoubleField(env, cls, fid, va_arg(args, jdouble)); 1512 break; 1513 1514 default: 1515 (*env)->FatalError(env, "JNU_SetStaticFieldByName: illegal signature"); 1516 } 1517 va_end(args); 1518 1519 done1: 1520 (*env)->DeleteLocalRef(env, cls); 1521 done2: 1522 if (hasException) { 1523 *hasException = (*env)->ExceptionCheck(env); 1524 } 1525 }