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 (strcmp(encname, "ISO-8859-1") == 0)) 665 fastEncoding = FAST_8859_1; 666 else if (strcmp(encname, "ISO646-US") == 0) 667 fastEncoding = FAST_646_US; 668 else if (strcmp(encname, "Cp1252") == 0 || 669 /* This is a temporary fix until we move */ 670 /* to wide character versions of all Windows */ 671 /* calls. */ 672 strcmp(encname, "utf-16le") == 0) 673 fastEncoding = FAST_CP1252; 674 else { 675 fastEncoding = NO_FAST_ENCODING; 676 jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc); 677 } 678 (*env)->ReleaseStringUTFChars(env, enc, encname); 679 } 680 } 681 } else { 682 (*env)->ExceptionClear(env); 683 } 684 } else { 685 (*env)->ExceptionClear(env); 686 } 687 (*env)->DeleteLocalRef(env, propname); 688 (*env)->DeleteLocalRef(env, enc); 689 690 /* Initialize method-id cache */ 691 String_getBytes_ID = (*env)->GetMethodID(env, strClazz, 692 "getBytes", "(Ljava/lang/String;)[B"); 693 CHECK_NULL(String_getBytes_ID); 694 String_init_ID = (*env)->GetMethodID(env, strClazz, 695 "<init>", "([BLjava/lang/String;)V"); 696 } 697 698 static jboolean isJNUEncodingSupported = JNI_FALSE; 699 static jboolean jnuEncodingSupported(JNIEnv *env) { 700 jboolean exe; 701 if (isJNUEncodingSupported == JNI_TRUE) { 702 return JNI_TRUE; 703 } 704 isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName ( 705 env, &exe, 706 "java/nio/charset/Charset", 707 "isSupported", 708 "(Ljava/lang/String;)Z", 709 jnuEncoding).z; 710 return isJNUEncodingSupported; 711 } 712 713 714 JNIEXPORT jstring 715 NewStringPlatform(JNIEnv *env, const char *str) 716 { 717 return JNU_NewStringPlatform(env, str); 718 } 719 720 JNIEXPORT jstring JNICALL 721 JNU_NewStringPlatform(JNIEnv *env, const char *str) 722 { 723 jstring result = NULL; 724 jbyteArray hab = 0; 725 int len; 726 727 if (fastEncoding == NO_ENCODING_YET) { 728 initializeEncoding(env); 729 JNU_CHECK_EXCEPTION_RETURN(env, NULL); 730 } 731 732 if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET)) 733 return newString8859_1(env, str); 734 if (fastEncoding == FAST_646_US) 735 return newString646_US(env, str); 736 if (fastEncoding == FAST_CP1252) 737 return newStringCp1252(env, str); 738 739 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 740 return NULL; 741 742 len = (int)strlen(str); 743 hab = (*env)->NewByteArray(env, len); 744 if (hab != 0) { 745 jclass strClazz = JNU_ClassString(env); 746 CHECK_NULL_RETURN(strClazz, 0); 747 (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str); 748 if (jnuEncodingSupported(env)) { 749 result = (*env)->NewObject(env, strClazz, 750 String_init_ID, hab, jnuEncoding); 751 } else { 752 /*If the encoding specified in sun.jnu.encoding is not endorsed 753 by "Charset.isSupported" we have to fall back to use String(byte[]) 754 explicitly here without specifying the encoding name, in which the 755 StringCoding class will pickup the iso-8859-1 as the fallback 756 converter for us. 757 */ 758 jmethodID mid = (*env)->GetMethodID(env, strClazz, 759 "<init>", "([B)V"); 760 if (mid != NULL) { 761 result = (*env)->NewObject(env, strClazz, mid, hab); 762 } 763 } 764 (*env)->DeleteLocalRef(env, hab); 765 return result; 766 } 767 return NULL; 768 } 769 770 JNIEXPORT const char * 771 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 772 { 773 return JNU_GetStringPlatformChars(env, jstr, isCopy); 774 } 775 776 JNIEXPORT const char * JNICALL 777 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 778 { 779 char *result = NULL; 780 jbyteArray hab = 0; 781 782 if (isCopy) 783 *isCopy = JNI_TRUE; 784 785 if (fastEncoding == NO_ENCODING_YET) { 786 initializeEncoding(env); 787 JNU_CHECK_EXCEPTION_RETURN(env, 0); 788 } 789 790 if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET)) 791 return getString8859_1Chars(env, jstr); 792 if (fastEncoding == FAST_646_US) 793 return getString646_USChars(env, jstr); 794 if (fastEncoding == FAST_CP1252) 795 return getStringCp1252Chars(env, jstr); 796 797 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 798 return 0; 799 800 if (jnuEncodingSupported(env)) { 801 hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding); 802 } else { 803 jmethodID mid; 804 jclass strClazz = JNU_ClassString(env); 805 CHECK_NULL_RETURN(strClazz, 0); 806 mid = (*env)->GetMethodID(env, strClazz, 807 "getBytes", "()[B"); 808 if (mid != NULL) { 809 hab = (*env)->CallObjectMethod(env, jstr, mid); 810 } 811 } 812 813 if (!(*env)->ExceptionCheck(env)) { 814 jint len = (*env)->GetArrayLength(env, hab); 815 result = MALLOC_MIN4(len); 816 if (result == 0) { 817 JNU_ThrowOutOfMemoryError(env, 0); 818 (*env)->DeleteLocalRef(env, hab); 819 return 0; 820 } 821 (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result); 822 result[len] = 0; /* NULL-terminate */ 823 } 824 825 (*env)->DeleteLocalRef(env, hab); 826 return result; 827 } 828 829 JNIEXPORT void JNICALL 830 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str) 831 { 832 free((void *)str); 833 } 834 835 /* 836 * Export the platform dependent path canonicalization so that 837 * VM can find it when loading system classes. 838 * This function is also used by the instrumentation agent. 839 */ 840 extern int canonicalize(char *path, const char *out, int len); 841 842 JNIEXPORT int 843 Canonicalize(JNIEnv *unused, char *orig, char *out, int len) 844 { 845 /* canonicalize an already natived path */ 846 return canonicalize(orig, out, len); 847 } 848 849 JNIEXPORT jclass JNICALL 850 JNU_ClassString(JNIEnv *env) 851 { 852 static jclass cls = 0; 853 if (cls == 0) { 854 jclass c; 855 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 856 return 0; 857 c = (*env)->FindClass(env, "java/lang/String"); 858 CHECK_NULL_RETURN(c, NULL); 859 cls = (*env)->NewGlobalRef(env, c); 860 (*env)->DeleteLocalRef(env, c); 861 } 862 return cls; 863 } 864 865 JNIEXPORT jclass JNICALL 866 JNU_ClassClass(JNIEnv *env) 867 { 868 static jclass cls = 0; 869 if (cls == 0) { 870 jclass c; 871 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 872 return 0; 873 c = (*env)->FindClass(env, "java/lang/Class"); 874 CHECK_NULL_RETURN(c, NULL); 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 CHECK_NULL_RETURN(c, NULL); 891 cls = (*env)->NewGlobalRef(env, c); 892 (*env)->DeleteLocalRef(env, c); 893 } 894 return cls; 895 } 896 897 JNIEXPORT jclass JNICALL 898 JNU_ClassThrowable(JNIEnv *env) 899 { 900 static jclass cls = 0; 901 if (cls == 0) { 902 jclass c; 903 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 904 return 0; 905 c = (*env)->FindClass(env, "java/lang/Throwable"); 906 CHECK_NULL_RETURN(c, NULL); 907 cls = (*env)->NewGlobalRef(env, c); 908 (*env)->DeleteLocalRef(env, c); 909 } 910 return cls; 911 } 912 913 JNIEXPORT jint JNICALL 914 JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, 915 jint count) 916 { 917 int i; 918 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 919 return -1; 920 for (i=0; i<count; i++) { 921 jstring p = (*env)->GetObjectArrayElement(env, src, i); 922 (*env)->SetObjectArrayElement(env, dst, i, p); 923 (*env)->DeleteLocalRef(env, p); 924 } 925 return 0; 926 } 927 928 JNIEXPORT void * JNICALL 929 JNU_GetEnv(JavaVM *vm, jint version) 930 { 931 void *env; 932 (*vm)->GetEnv(vm, &env, version); 933 return env; 934 } 935 936 JNIEXPORT jint JNICALL 937 JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char* classname) 938 { 939 jclass cls; 940 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 941 return JNI_ERR; 942 cls = (*env)->FindClass(env, classname); 943 if (cls != NULL) { 944 jint result = (*env)->IsInstanceOf(env, object, cls); 945 (*env)->DeleteLocalRef(env, cls); 946 return result; 947 } 948 return JNI_ERR; 949 } 950 951 JNIEXPORT jboolean JNICALL 952 JNU_Equals(JNIEnv *env, jobject object1, jobject object2) 953 { 954 static jmethodID mid = NULL; 955 if (mid == NULL) { 956 jclass objClazz = JNU_ClassObject(env); 957 CHECK_NULL_RETURN(objClazz, JNI_FALSE); 958 mid = (*env)->GetMethodID(env, objClazz, "equals", 959 "(Ljava/lang/Object;)Z"); 960 CHECK_NULL_RETURN(mid, JNI_FALSE); 961 } 962 return (*env)->CallBooleanMethod(env, object1, mid, object2); 963 } 964 965 966 /************************************************************************ 967 * Thread calls 968 */ 969 970 static jmethodID Object_waitMID; 971 static jmethodID Object_notifyMID; 972 static jmethodID Object_notifyAllMID; 973 974 JNIEXPORT void JNICALL 975 JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout) 976 { 977 if (object == NULL) { 978 JNU_ThrowNullPointerException(env, "JNU_MonitorWait argument"); 979 return; 980 } 981 if (Object_waitMID == NULL) { 982 jclass cls = JNU_ClassObject(env); 983 if (cls == NULL) { 984 return; 985 } 986 Object_waitMID = (*env)->GetMethodID(env, cls, "wait", "(J)V"); 987 if (Object_waitMID == NULL) { 988 return; 989 } 990 } 991 (*env)->CallVoidMethod(env, object, Object_waitMID, timeout); 992 } 993 994 JNIEXPORT void JNICALL 995 JNU_Notify(JNIEnv *env, jobject object) 996 { 997 if (object == NULL) { 998 JNU_ThrowNullPointerException(env, "JNU_Notify argument"); 999 return; 1000 } 1001 if (Object_notifyMID == NULL) { 1002 jclass cls = JNU_ClassObject(env); 1003 if (cls == NULL) { 1004 return; 1005 } 1006 Object_notifyMID = (*env)->GetMethodID(env, cls, "notify", "()V"); 1007 if (Object_notifyMID == NULL) { 1008 return; 1009 } 1010 } 1011 (*env)->CallVoidMethod(env, object, Object_notifyMID); 1012 } 1013 1014 JNIEXPORT void JNICALL 1015 JNU_NotifyAll(JNIEnv *env, jobject object) 1016 { 1017 if (object == NULL) { 1018 JNU_ThrowNullPointerException(env, "JNU_NotifyAll argument"); 1019 return; 1020 } 1021 if (Object_notifyAllMID == NULL) { 1022 jclass cls = JNU_ClassObject(env); 1023 if (cls == NULL) { 1024 return; 1025 } 1026 Object_notifyAllMID = (*env)->GetMethodID(env, cls,"notifyAll", "()V"); 1027 if (Object_notifyAllMID == NULL) { 1028 return; 1029 } 1030 } 1031 (*env)->CallVoidMethod(env, object, Object_notifyAllMID); 1032 } 1033 1034 1035 /************************************************************************ 1036 * Debugging utilities 1037 */ 1038 1039 JNIEXPORT void JNICALL 1040 JNU_PrintString(JNIEnv *env, char *hdr, jstring string) 1041 { 1042 if (string == NULL) { 1043 fprintf(stderr, "%s: is NULL\n", hdr); 1044 } else { 1045 const char *stringPtr = JNU_GetStringPlatformChars(env, string, 0); 1046 if (stringPtr == 0) 1047 return; 1048 fprintf(stderr, "%s: %s\n", hdr, stringPtr); 1049 JNU_ReleaseStringPlatformChars(env, string, stringPtr); 1050 } 1051 } 1052 1053 JNIEXPORT void JNICALL 1054 JNU_PrintClass(JNIEnv *env, char* hdr, jobject object) 1055 { 1056 if (object == NULL) { 1057 fprintf(stderr, "%s: object is NULL\n", hdr); 1058 return; 1059 } else { 1060 jclass cls = (*env)->GetObjectClass(env, object); 1061 jstring clsName = JNU_ToString(env, cls); 1062 if (clsName == NULL) { 1063 JNU_PrintString(env, hdr, clsName); 1064 } 1065 (*env)->DeleteLocalRef(env, cls); 1066 (*env)->DeleteLocalRef(env, clsName); 1067 } 1068 } 1069 1070 JNIEXPORT jstring JNICALL 1071 JNU_ToString(JNIEnv *env, jobject object) 1072 { 1073 if (object == NULL) { 1074 return (*env)->NewStringUTF(env, "NULL"); 1075 } else { 1076 return (jstring)JNU_CallMethodByName(env, 1077 NULL, 1078 object, 1079 "toString", 1080 "()Ljava/lang/String;").l; 1081 } 1082 } 1083 1084 JNIEXPORT jvalue JNICALL 1085 JNU_GetFieldByName(JNIEnv *env, 1086 jboolean *hasException, 1087 jobject obj, 1088 const char *name, 1089 const char *signature) 1090 { 1091 jclass cls; 1092 jfieldID fid; 1093 jvalue result; 1094 1095 result.i = 0; 1096 1097 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1098 goto done2; 1099 1100 cls = (*env)->GetObjectClass(env, obj); 1101 fid = (*env)->GetFieldID(env, cls, name, signature); 1102 if (fid == 0) 1103 goto done1; 1104 1105 switch (*signature) { 1106 case '[': 1107 case 'L': 1108 result.l = (*env)->GetObjectField(env, obj, fid); 1109 break; 1110 case 'Z': 1111 result.z = (*env)->GetBooleanField(env, obj, fid); 1112 break; 1113 case 'B': 1114 result.b = (*env)->GetByteField(env, obj, fid); 1115 break; 1116 case 'C': 1117 result.c = (*env)->GetCharField(env, obj, fid); 1118 break; 1119 case 'S': 1120 result.s = (*env)->GetShortField(env, obj, fid); 1121 break; 1122 case 'I': 1123 result.i = (*env)->GetIntField(env, obj, fid); 1124 break; 1125 case 'J': 1126 result.j = (*env)->GetLongField(env, obj, fid); 1127 break; 1128 case 'F': 1129 result.f = (*env)->GetFloatField(env, obj, fid); 1130 break; 1131 case 'D': 1132 result.d = (*env)->GetDoubleField(env, obj, fid); 1133 break; 1134 1135 default: 1136 (*env)->FatalError(env, "JNU_GetFieldByName: illegal signature"); 1137 } 1138 1139 done1: 1140 (*env)->DeleteLocalRef(env, cls); 1141 done2: 1142 if (hasException) { 1143 *hasException = (*env)->ExceptionCheck(env); 1144 } 1145 return result; 1146 } 1147 1148 JNIEXPORT void JNICALL 1149 JNU_SetFieldByName(JNIEnv *env, 1150 jboolean *hasException, 1151 jobject obj, 1152 const char *name, 1153 const char *signature, 1154 ...) 1155 { 1156 jclass cls; 1157 jfieldID fid; 1158 va_list args; 1159 1160 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1161 goto done2; 1162 1163 cls = (*env)->GetObjectClass(env, obj); 1164 fid = (*env)->GetFieldID(env, cls, name, signature); 1165 if (fid == 0) 1166 goto done1; 1167 1168 va_start(args, signature); 1169 switch (*signature) { 1170 case '[': 1171 case 'L': 1172 (*env)->SetObjectField(env, obj, fid, va_arg(args, jobject)); 1173 break; 1174 case 'Z': 1175 (*env)->SetBooleanField(env, obj, fid, (jboolean)va_arg(args, int)); 1176 break; 1177 case 'B': 1178 (*env)->SetByteField(env, obj, fid, (jbyte)va_arg(args, int)); 1179 break; 1180 case 'C': 1181 (*env)->SetCharField(env, obj, fid, (jchar)va_arg(args, int)); 1182 break; 1183 case 'S': 1184 (*env)->SetShortField(env, obj, fid, (jshort)va_arg(args, int)); 1185 break; 1186 case 'I': 1187 (*env)->SetIntField(env, obj, fid, va_arg(args, jint)); 1188 break; 1189 case 'J': 1190 (*env)->SetLongField(env, obj, fid, va_arg(args, jlong)); 1191 break; 1192 case 'F': 1193 (*env)->SetFloatField(env, obj, fid, (jfloat)va_arg(args, jdouble)); 1194 break; 1195 case 'D': 1196 (*env)->SetDoubleField(env, obj, fid, va_arg(args, jdouble)); 1197 break; 1198 1199 default: 1200 (*env)->FatalError(env, "JNU_SetFieldByName: illegal signature"); 1201 } 1202 va_end(args); 1203 1204 done1: 1205 (*env)->DeleteLocalRef(env, cls); 1206 done2: 1207 if (hasException) { 1208 *hasException = (*env)->ExceptionCheck(env); 1209 } 1210 } 1211 1212 JNIEXPORT jvalue JNICALL 1213 JNU_GetStaticFieldByName(JNIEnv *env, 1214 jboolean *hasException, 1215 const char *classname, 1216 const char *name, 1217 const char *signature) 1218 { 1219 jclass cls; 1220 jfieldID fid; 1221 jvalue result; 1222 1223 result.i = 0; 1224 1225 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1226 goto done2; 1227 1228 cls = (*env)->FindClass(env, classname); 1229 if (cls == 0) 1230 goto done2; 1231 1232 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1233 if (fid == 0) 1234 goto done1; 1235 1236 switch (*signature) { 1237 case '[': 1238 case 'L': 1239 result.l = (*env)->GetStaticObjectField(env, cls, fid); 1240 break; 1241 case 'Z': 1242 result.z = (*env)->GetStaticBooleanField(env, cls, fid); 1243 break; 1244 case 'B': 1245 result.b = (*env)->GetStaticByteField(env, cls, fid); 1246 break; 1247 case 'C': 1248 result.c = (*env)->GetStaticCharField(env, cls, fid); 1249 break; 1250 case 'S': 1251 result.s = (*env)->GetStaticShortField(env, cls, fid); 1252 break; 1253 case 'I': 1254 result.i = (*env)->GetStaticIntField(env, cls, fid); 1255 break; 1256 case 'J': 1257 result.j = (*env)->GetStaticLongField(env, cls, fid); 1258 break; 1259 case 'F': 1260 result.f = (*env)->GetStaticFloatField(env, cls, fid); 1261 break; 1262 case 'D': 1263 result.d = (*env)->GetStaticDoubleField(env, cls, fid); 1264 break; 1265 1266 default: 1267 (*env)->FatalError(env, "JNU_GetStaticFieldByName: illegal signature"); 1268 } 1269 1270 done1: 1271 (*env)->DeleteLocalRef(env, cls); 1272 done2: 1273 if (hasException) { 1274 *hasException = (*env)->ExceptionCheck(env); 1275 } 1276 return result; 1277 } 1278 1279 JNIEXPORT void JNICALL 1280 JNU_SetStaticFieldByName(JNIEnv *env, 1281 jboolean *hasException, 1282 const char *classname, 1283 const char *name, 1284 const char *signature, 1285 ...) 1286 { 1287 jclass cls; 1288 jfieldID fid; 1289 va_list args; 1290 1291 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1292 goto done2; 1293 1294 cls = (*env)->FindClass(env, classname); 1295 if (cls == 0) 1296 goto done2; 1297 1298 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1299 if (fid == 0) 1300 goto done1; 1301 1302 va_start(args, signature); 1303 switch (*signature) { 1304 case '[': 1305 case 'L': 1306 (*env)->SetStaticObjectField(env, cls, fid, va_arg(args, jobject)); 1307 break; 1308 case 'Z': 1309 (*env)->SetStaticBooleanField(env, cls, fid, (jboolean)va_arg(args, int)); 1310 break; 1311 case 'B': 1312 (*env)->SetStaticByteField(env, cls, fid, (jbyte)va_arg(args, int)); 1313 break; 1314 case 'C': 1315 (*env)->SetStaticCharField(env, cls, fid, (jchar)va_arg(args, int)); 1316 break; 1317 case 'S': 1318 (*env)->SetStaticShortField(env, cls, fid, (jshort)va_arg(args, int)); 1319 break; 1320 case 'I': 1321 (*env)->SetStaticIntField(env, cls, fid, va_arg(args, jint)); 1322 break; 1323 case 'J': 1324 (*env)->SetStaticLongField(env, cls, fid, va_arg(args, jlong)); 1325 break; 1326 case 'F': 1327 (*env)->SetStaticFloatField(env, cls, fid, (jfloat)va_arg(args, jdouble)); 1328 break; 1329 case 'D': 1330 (*env)->SetStaticDoubleField(env, cls, fid, va_arg(args, jdouble)); 1331 break; 1332 1333 default: 1334 (*env)->FatalError(env, "JNU_SetStaticFieldByName: illegal signature"); 1335 } 1336 va_end(args); 1337 1338 done1: 1339 (*env)->DeleteLocalRef(env, cls); 1340 done2: 1341 if (hasException) { 1342 *hasException = (*env)->ExceptionCheck(env); 1343 } 1344 }