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