001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.jni; 014 015 import java.lang.reflect.Constructor; 016 import java.lang.reflect.Field; 017 import java.lang.reflect.Method; 018 import java.nio.Buffer; 019 import org.jikesrvm.ArchitectureSpecific.JNIHelpers; 020 import org.jikesrvm.VM; 021 import org.jikesrvm.Properties; 022 import org.jikesrvm.SizeConstants; 023 import org.jikesrvm.classloader.RVMArray; 024 import org.jikesrvm.classloader.Atom; 025 import org.jikesrvm.classloader.RVMClass; 026 import org.jikesrvm.classloader.RVMClassLoader; 027 import org.jikesrvm.classloader.RVMField; 028 import org.jikesrvm.classloader.MemberReference; 029 import org.jikesrvm.classloader.RVMMethod; 030 import org.jikesrvm.classloader.NativeMethod; 031 import org.jikesrvm.classloader.RVMType; 032 import org.jikesrvm.classloader.TypeReference; 033 import org.jikesrvm.classloader.UTF8Convert; 034 import org.jikesrvm.mm.mminterface.MemoryManager; 035 import org.jikesrvm.objectmodel.ObjectModel; 036 import org.jikesrvm.runtime.BootRecord; 037 import org.jikesrvm.runtime.Magic; 038 import org.jikesrvm.runtime.Memory; 039 import org.jikesrvm.runtime.Reflection; 040 import org.jikesrvm.runtime.RuntimeEntrypoints; 041 import org.jikesrvm.util.AddressInputStream; 042 043 import static org.jikesrvm.runtime.SysCall.sysCall; 044 import org.vmmagic.pragma.NativeBridge; 045 import org.vmmagic.unboxed.Address; 046 import org.vmmagic.unboxed.AddressArray; 047 import org.vmmagic.unboxed.Offset; 048 049 /** 050 * This class implements the 232 JNI functions. 051 * All methods here will be specially compiled with the necessary prolog to 052 * perform the transition from native code (Linux/AIX/OSX convention) to RVM. 053 * For this reason, no Java methods (including the JNI methods here) can call 054 * any methods in this class from within Java. These JNI methods are to 055 * be invoked from native C or C++. They're all declared private to enforce 056 * this discipline. <br> 057 * 058 * The first argument for all the functions is the JNIEnvironment object 059 * of the thread. <br> 060 * 061 * The second argument is a JREF index for either the RVMClass object 062 * or the object instance itself. To get the actual object, we use 063 * the access method in JNIEnvironment and cast the reference as 064 * needed. <br> 065 * 066 * NOTE: 067 * <ol> 068 * <li> JREF index refers to the index into the side table of references 069 * maintained by the JNIEnvironment for each thread. Except for some cases 070 * of array access, no references are passed directly to the native code; 071 * rather, the references are kept in the table and the index is passed to the 072 * native procedure. The JREF index are used by the JNI code to retrieve the 073 * corresponding reference. </li> 074 * 075 * <li> Strings from C are seen as raw address (int) and need to be cloned as 076 * Java Strings </li> 077 * 078 * <li> Because of many of the transformation above, the method signature of the 079 * JNI functions may not match its definition in the jni.h file </li> 080 * 081 * <li> For exception handling, all JNI functions are wrapped in Try/Catch block 082 * to catch all exception generated during JNI call, then these exceptions 083 * or the appropriate exception to be thrown according to the spec is recorded 084 * in JNIEnvironment.pendingException. When the native code returns to the 085 * the Java caller, the epilogue in the glue code will check for the pending 086 * exception and deliver it to the caller as if executing an athrow bytecode 087 * in the caller. </li> 088 * </ol> 089 * 090 * Known Problems with our JNI implementation: 091 * <ol> 092 * <li>We can not return a global reference (whether weak 093 * or strong) from a JNI function. We can only return local refs. 094 * <li>We do not implement all of the invocation API; we don't support the 095 * concept of a regular native program that links with "libjava" and 096 * creates and destroys virtual machines. 097 * <li>Similarly, we can not attach and detach a native threads to and from 098 * the VM. 099 * <li>We don't really free local refs when we call the 100 * {@link #PopLocalFrame} method. 101 * </ol> 102 */ 103 @SuppressWarnings({"unused", "UnusedDeclaration"}) 104 // methods are called from native code 105 @NativeBridge 106 public class JNIFunctions implements SizeConstants { 107 // one message for each JNI function called from native 108 public static final boolean traceJNI = Properties.verboseJNI; 109 110 // number of JNI function entries 111 public static final int FUNCTIONCOUNT = 232; // JNI 1.4 112 113 /** 114 * GetVersion: the version of the JNI 115 * @param env A JREF index for the JNI environment object 116 * @return 0x00010004 for JNI 1.4, 0x00010002 for JNI 1.2, 117 * 0x00010001 for JNI 1.1, 118 */ 119 private static int GetVersion(JNIEnvironment env) { 120 if (traceJNI) VM.sysWrite("JNI called: GetVersion \n"); 121 RuntimeEntrypoints.checkJNICountDownToGC(); 122 123 return 0x00010004; // JNI 1.4 124 } 125 126 /** 127 * DefineClass: Loads a class from a buffer of raw class data. 128 * @param env A JREF index for the JNI environment object 129 * @param classNameAddress a raw address to a null-terminated string in C for the class name 130 * @param classLoader a JREF index for the class loader assigned to the defined class 131 * @param data buffer containing the <tt>.class</tt> file 132 * @param dataLen buffer length 133 * @return a JREF index for the Java Class object, or 0 if not found 134 * @exception ClassFormatError if the class data does not specify a valid class 135 * @exception ClassCircularityError (not implemented) 136 * @exception OutOfMemoryError (not implemented) 137 */ 138 private static int DefineClass(JNIEnvironment env, Address classNameAddress, int classLoader, Address data, 139 int dataLen) { 140 if (traceJNI) VM.sysWrite("JNI called: DefineClass \n"); 141 RuntimeEntrypoints.checkJNICountDownToGC(); 142 143 try { 144 String classString = null; 145 if (!classNameAddress.isZero()) { 146 JNIHelpers.createStringFromC(classNameAddress); 147 } 148 ClassLoader cl; 149 if (classLoader == 0) { 150 cl = RVMClass.getClassLoaderFromStackFrame(1); 151 } else { 152 cl = (ClassLoader) env.getJNIRef(classLoader); 153 } 154 AddressInputStream reader = new AddressInputStream(data, Offset.fromIntZeroExtend(dataLen)); 155 156 final RVMType vmType = RVMClassLoader.defineClassInternal(classString, reader, cl); 157 return env.pushJNIRef(vmType.getClassForType()); 158 } catch (Throwable unexpected) { 159 if (traceJNI) unexpected.printStackTrace(System.err); 160 env.recordException(unexpected); 161 return 0; 162 } 163 164 } 165 166 /** 167 * FindClass: given a class name, find its RVMClass, or 0 if not found 168 * @param env A JREF index for the JNI environment object 169 * @param classNameAddress a raw address to a null-terminated string in C for the class name 170 * @return a JREF index for the Java Class object, or 0 if not found 171 * @exception ClassFormatError (not implemented) 172 * @exception ClassCircularityError (not implemented) 173 * @exception NoClassDefFoundError if the class cannot be found 174 * @exception OutOfMemoryError (not implemented) 175 * @exception ExceptionInInitializerError (not implemented) 176 */ 177 private static int FindClass(JNIEnvironment env, Address classNameAddress) { 178 if (traceJNI) VM.sysWrite("JNI called: FindClass \n"); 179 RuntimeEntrypoints.checkJNICountDownToGC(); 180 181 String classString = null; 182 try { 183 classString = JNIHelpers.createStringFromC(classNameAddress); 184 classString = classString.replace('/', '.'); 185 if (classString.startsWith("L") && classString.endsWith(";")) { 186 classString = classString.substring(1, classString.length() - 1); 187 } 188 if (traceJNI) VM.sysWriteln(classString); 189 ClassLoader cl = RVMClass.getClassLoaderFromStackFrame(1); 190 Class<?> matchedClass = Class.forName(classString.replace('/', '.'), true, cl); 191 int result = env.pushJNIRef(matchedClass); 192 if (traceJNI) VM.sysWriteln("FindClass returning ",result); 193 return result; 194 } catch (ClassNotFoundException e) { 195 if (traceJNI) e.printStackTrace(System.err); 196 env.recordException(new NoClassDefFoundError(classString)); 197 return 0; 198 } catch (Throwable unexpected) { 199 if (traceJNI) { 200 if (VM.fullyBooted) { 201 unexpected.printStackTrace(System.err); 202 } else { 203 VM.sysWrite("Unexpected exception ", unexpected.getClass().toString()); 204 VM.sysWriteln(" to early in VM boot up to print ", unexpected.getMessage()); 205 } 206 } 207 env.recordException(unexpected); 208 return 0; 209 } 210 } 211 212 /** 213 * GetSuperclass: find the superclass given a class 214 * @param env A JREF index for the JNI environment object 215 * @param classJREF a JREF index for the class object 216 * @return a JREF index for the super class object, or 0 if the given class 217 * is java.lang.Object or an interface 218 */ 219 private static int GetSuperclass(JNIEnvironment env, int classJREF) { 220 if (traceJNI) VM.sysWrite("JNI called: GetSuperclass \n"); 221 RuntimeEntrypoints.checkJNICountDownToGC(); 222 223 try { 224 Class<?> cls = (Class<?>) env.getJNIRef(classJREF); 225 Class<?> supercls = cls.getSuperclass(); 226 return supercls == null ? 0 : env.pushJNIRef(supercls); 227 } catch (Throwable unexpected) { 228 if (traceJNI) unexpected.printStackTrace(System.err); 229 env.recordException(unexpected); 230 return 0; 231 } 232 } 233 234 /** 235 * IsAssignableFrom: determine if an an object of class or interface cls1 236 * can be cast to the class or interface cls2 237 * @param env A JREF index for the JNI environment object 238 * @param firstClassJREF a JREF index for the first class object 239 * @param secondClassJREF a JREF index for the second class object 240 * @return true if cls1 can be assigned to cls2 241 */ 242 private static boolean IsAssignableFrom(JNIEnvironment env, int firstClassJREF, int secondClassJREF) { 243 if (traceJNI) VM.sysWrite("JNI called: IsAssignableFrom \n"); 244 RuntimeEntrypoints.checkJNICountDownToGC(); 245 246 try { 247 Class<?> cls1 = (Class<?>) env.getJNIRef(firstClassJREF); 248 Class<?> cls2 = (Class<?>) env.getJNIRef(secondClassJREF); 249 return !(cls1 == null || cls2 == null) && cls2.isAssignableFrom(cls1); 250 } catch (Throwable unexpected) { 251 if (traceJNI) unexpected.printStackTrace(System.err); 252 env.recordException(unexpected); 253 return false; 254 } 255 } 256 257 /** 258 * Throw: register a {@link Throwable} object as a pending exception, to be 259 * delivered on return to the Java caller 260 * @param env A JREF index for the JNI environment object 261 * @param exceptionJREF A JREF index for the {@link Throwable} object to be 262 * thrown 263 * @return 0 if successful, -1 if not 264 */ 265 private static int Throw(JNIEnvironment env, int exceptionJREF) { 266 if (traceJNI) VM.sysWrite("JNI called: Throw \n"); 267 RuntimeEntrypoints.checkJNICountDownToGC(); 268 269 try { 270 env.recordException((Throwable) env.getJNIRef(exceptionJREF)); 271 return 0; 272 } catch (Throwable unexpected) { 273 if (traceJNI) unexpected.printStackTrace(System.err); 274 env.recordException(unexpected); 275 return -1; 276 } 277 } 278 279 /** 280 * ThrowNew 281 * @param env A JREF index for the JNI environment object 282 * @param throwableClassJREF a JREF index for the class object of the exception 283 * @param exceptionNameAddress an address of the string in C 284 * @return 0 if successful, -1 otherwise 285 */ 286 private static int ThrowNew(JNIEnvironment env, int throwableClassJREF, Address exceptionNameAddress) { 287 if (traceJNI) VM.sysWrite("JNI called: ThrowNew \n"); 288 RuntimeEntrypoints.checkJNICountDownToGC(); 289 290 try { 291 Class<?> cls = (Class<?>) env.getJNIRef(throwableClassJREF); 292 // find the constructor that has a string as a parameter 293 Class<?>[] argClasses = new Class[1]; 294 argClasses[0] = RVMType.JavaLangStringType.getClassForType(); 295 Constructor<?> constMethod = cls.getConstructor(argClasses); 296 // prepare the parameter list for reflective invocation 297 Object[] argObjs = new Object[1]; 298 argObjs[0] = JNIHelpers.createStringFromC(exceptionNameAddress); 299 300 // invoke the constructor to obtain a new Throwable object 301 env.recordException((Throwable) constMethod.newInstance(argObjs)); 302 return 0; 303 } catch (Throwable unexpected) { 304 if (traceJNI) unexpected.printStackTrace(System.err); 305 env.recordException(unexpected); 306 return -1; 307 } 308 309 } 310 311 /** 312 * ExceptionOccurred 313 * @param env A JREF index for the JNI environment object 314 * @return a JREF index for the pending exception or null if nothing pending 315 */ 316 private static int ExceptionOccurred(JNIEnvironment env) { 317 if (traceJNI) VM.sysWrite("JNI called: ExceptionOccurred \n"); 318 RuntimeEntrypoints.checkJNICountDownToGC(); 319 320 try { 321 Throwable e = env.getException(); 322 if (e == null) { 323 return 0; 324 } else { 325 if (traceJNI) System.err.println(e.toString()); 326 return env.pushJNIRef(e); 327 } 328 } catch (Throwable unexpected) { 329 if (traceJNI) unexpected.printStackTrace(System.err); 330 env.recordException(unexpected); 331 return env.pushJNIRef(unexpected); 332 } 333 } 334 335 /** 336 * ExceptionDescribe: print the exception description and the stack trace back, 337 * then clear the exception 338 * @param env A JREF index for the JNI environment object 339 */ 340 private static void ExceptionDescribe(JNIEnvironment env) { 341 if (traceJNI) VM.sysWrite("JNI called: ExceptionDescribe \n"); 342 RuntimeEntrypoints.checkJNICountDownToGC(); 343 344 try { 345 Throwable e = env.getException(); 346 if (e != null) { 347 env.recordException(null); 348 e.printStackTrace(System.err); 349 } 350 } catch (Throwable unexpected) { 351 if (traceJNI) unexpected.printStackTrace(System.err); 352 env.recordException(null); // clear old exception and register new one 353 env.recordException(unexpected); 354 } 355 } 356 357 /** 358 * ExceptionClear 359 * @param env A JREF index for the JNI environment object 360 */ 361 private static void ExceptionClear(JNIEnvironment env) { 362 if (traceJNI) VM.sysWrite("JNI called: ExceptionClear \n"); 363 RuntimeEntrypoints.checkJNICountDownToGC(); 364 365 try { 366 env.recordException(null); 367 } catch (Throwable unexpected) { 368 if (traceJNI) unexpected.printStackTrace(System.err); 369 env.recordException(null); // clear old exception and register new one 370 env.recordException(unexpected); 371 } 372 } 373 374 /** 375 * FatalError: print a message and terminate the VM 376 * @param env A JREF index for the JNI environment object 377 * @param messageAddress an address of the string in C 378 */ 379 private static void FatalError(JNIEnvironment env, Address messageAddress) { 380 if (traceJNI) VM.sysWrite("JNI called: FatalError \n"); 381 RuntimeEntrypoints.checkJNICountDownToGC(); 382 383 try { 384 VM.sysWrite(JNIHelpers.createStringFromC(messageAddress)); 385 System.exit(VM.EXIT_STATUS_JNI_TROUBLE); 386 } catch (Throwable unexpected) { 387 if (traceJNI) unexpected.printStackTrace(System.err); 388 System.exit(VM.EXIT_STATUS_RECURSIVELY_SHUTTING_DOWN); 389 } 390 } 391 392 private static int NewGlobalRef(JNIEnvironment env, int objectJREF) { 393 if (traceJNI) VM.sysWrite("JNI called: NewGlobalRef\n"); 394 RuntimeEntrypoints.checkJNICountDownToGC(); 395 396 try { 397 Object obj1 = env.getJNIRef(objectJREF); 398 return JNIGlobalRefTable.newGlobalRef(obj1); 399 } catch (Throwable unexpected) { 400 if (traceJNI) unexpected.printStackTrace(System.err); 401 env.recordException(unexpected); 402 return 0; 403 } 404 } 405 406 private static void DeleteGlobalRef(JNIEnvironment env, int refJREF) { 407 if (traceJNI) VM.sysWrite("JNI called: DeleteGlobalRef\n"); 408 RuntimeEntrypoints.checkJNICountDownToGC(); 409 410 try { 411 JNIGlobalRefTable.deleteGlobalRef(refJREF); 412 } catch (Throwable unexpected) { 413 if (traceJNI) unexpected.printStackTrace(System.err); 414 env.recordException(unexpected); 415 } 416 } 417 418 private static void DeleteLocalRef(JNIEnvironment env, int objJREF) { 419 if (traceJNI) VM.sysWrite("JNI called: DeleteLocalRef\n"); 420 RuntimeEntrypoints.checkJNICountDownToGC(); 421 422 try { 423 env.deleteJNIRef(objJREF); 424 } catch (ArrayIndexOutOfBoundsException e) { 425 VM.sysFail("JNI refs array confused, or DeleteLocalRef gave us a bad JREF argument:", objJREF); 426 } catch (Throwable unexpected) { 427 if (traceJNI) unexpected.printStackTrace(System.err); 428 env.recordException(unexpected); 429 } 430 } 431 432 /** 433 * IsSameObject: determine if two references point to the same object 434 * @param env A JREF index for the JNI environment object 435 * @param obj1JREF A JREF index for the first object 436 * @param obj2JREF A JREF index for the second object 437 * @return <code>true</code> if it's the same object, false otherwise 438 */ 439 private static boolean IsSameObject(JNIEnvironment env, int obj1JREF, int obj2JREF) { 440 if (traceJNI) VM.sysWrite("JNI called: IsSameObject \n"); 441 RuntimeEntrypoints.checkJNICountDownToGC(); 442 443 try { 444 Object obj1 = env.getJNIRef(obj1JREF); 445 Object obj2 = env.getJNIRef(obj2JREF); 446 return obj1 == obj2; 447 } catch (Throwable unexpected) { 448 if (traceJNI) unexpected.printStackTrace(System.err); 449 env.recordException(null); // clear old exception and register new one 450 env.recordException(unexpected); 451 return false; 452 } 453 } 454 455 /** 456 * AllocObject: allocate the space for an object without running any constructor 457 * the header is filled and the fields are initialized to null 458 * @param env A JREF index for the JNI environment object 459 * @param classJREF a JREF index for the class object 460 * @return a JREF index for the uninitialized object 461 * @exception InstantiationException if the class is abstract or is an interface 462 * @exception OutOfMemoryError if no more memory to allocate 463 */ 464 private static int AllocObject(JNIEnvironment env, int classJREF) throws InstantiationException, OutOfMemoryError { 465 if (traceJNI) VM.sysWrite("JNI called: AllocObject \n"); 466 RuntimeEntrypoints.checkJNICountDownToGC(); 467 468 try { 469 Class<?> javaCls = (Class<?>) env.getJNIRef(classJREF); 470 RVMType type = java.lang.JikesRVMSupport.getTypeForClass(javaCls); 471 if (type.isArrayType() || type.isPrimitiveType() || type.isUnboxedType()) { 472 env.recordException(new InstantiationException()); 473 return 0; 474 } 475 RVMClass cls = type.asClass(); 476 if (cls.isAbstract() || cls.isInterface()) { 477 env.recordException(new InstantiationException()); 478 return 0; 479 } 480 Object newObj = RuntimeEntrypoints.resolvedNewScalar(cls); 481 return env.pushJNIRef(newObj); 482 } catch (Throwable unexpected) { 483 if (traceJNI) unexpected.printStackTrace(System.err); 484 env.recordException(unexpected); 485 return 0; 486 } 487 } 488 489 /** 490 * NewObject: create a new object instance 491 * NOTE: the vararg's are not visible in the method signature here; 492 * they are saved in the caller frame and the glue frame 493 * @param env A JREF index for the JNI environment object 494 * @param classJREF a JREF index for the class object 495 * @param methodID id of a MethodReference 496 * @return the new object instance 497 * @exception InstantiationException if the class is abstract or is an interface 498 * @exception OutOfMemoryError if no more memory to allocate 499 */ 500 private static int NewObject(JNIEnvironment env, int classJREF, int methodID) throws Exception { 501 if (traceJNI) VM.sysWrite("JNI called: NewObject \n"); 502 RuntimeEntrypoints.checkJNICountDownToGC(); 503 504 try { 505 Class<?> cls = (Class<?>) env.getJNIRef(classJREF); 506 RVMClass vmcls = java.lang.JikesRVMSupport.getTypeForClass(cls).asClass(); 507 508 if (vmcls.isAbstract() || vmcls.isInterface()) { 509 env.recordException(new InstantiationException()); 510 return 0; 511 } 512 513 Object newobj = JNIHelpers.invokeInitializer(cls, methodID, Address.zero(), false, true); 514 515 return env.pushJNIRef(newobj); 516 } catch (Throwable unexpected) { 517 if (traceJNI) unexpected.printStackTrace(System.err); 518 env.recordException(unexpected); 519 return 0; 520 } 521 } 522 523 /** 524 * NewObjectV: create a new object instance 525 * @param env A JREF index for the JNI environment object 526 * @param classJREF a JREF index for the class object 527 * @param methodID id of a MethodReference 528 * @param argAddress a raw address to a variable argument list, each element is 1-word or 529 * 2-words of the appropriate type for the constructor invocation 530 * @return the new object instance 531 * @exception InstantiationException if the class is abstract or is an interface 532 * @exception OutOfMemoryError if no more memory to allocate 533 */ 534 private static int NewObjectV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 535 throws Exception { 536 if (traceJNI) VM.sysWrite("JNI called: NewObjectV \n"); 537 RuntimeEntrypoints.checkJNICountDownToGC(); 538 539 try { 540 Class<?> cls = (Class<?>) env.getJNIRef(classJREF); 541 RVMClass vmcls = java.lang.JikesRVMSupport.getTypeForClass(cls).asClass(); 542 if (vmcls.isAbstract() || vmcls.isInterface()) { 543 env.recordException(new InstantiationException()); 544 return 0; 545 } 546 547 Object newobj = JNIHelpers.invokeInitializer(cls, methodID, argAddress, false, false); 548 549 return env.pushJNIRef(newobj); 550 } catch (Throwable unexpected) { 551 if (traceJNI) unexpected.printStackTrace(System.err); 552 env.recordException(unexpected); 553 return 0; 554 } 555 } 556 557 /** 558 * NewObjectA: create a new object instance 559 * @param env A JREF index for the JNI environment object 560 * @param classJREF a JREF index for the class object 561 * @param methodID id of a MethodReference 562 * @param argAddress a raw address to an array of unions in C, each element is 2-word and 563 * hold an argument of the appropriate type for the constructor invocation 564 * @exception InstantiationException if the class is abstract or is an interface 565 * @exception OutOfMemoryError if no more memory to allocate 566 * @return the new object instance 567 */ 568 private static int NewObjectA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 569 throws Exception { 570 if (traceJNI) VM.sysWrite("JNI called: NewObjectA \n"); 571 RuntimeEntrypoints.checkJNICountDownToGC(); 572 573 try { 574 Class<?> cls = (Class<?>) env.getJNIRef(classJREF); 575 RVMClass vmcls = java.lang.JikesRVMSupport.getTypeForClass(cls).asClass(); 576 577 if (vmcls.isAbstract() || vmcls.isInterface()) { 578 env.recordException(new InstantiationException()); 579 return 0; 580 } 581 582 Object newobj = JNIHelpers.invokeInitializer(cls, methodID, argAddress, true, false); 583 584 return env.pushJNIRef(newobj); 585 } catch (Throwable unexpected) { 586 if (traceJNI) unexpected.printStackTrace(System.err); 587 env.recordException(unexpected); 588 return 0; 589 } 590 } 591 592 /** 593 * GetObjectClass 594 * @param env A JREF index for the JNI environment object 595 * @param objJREF a JREF index for the object to check 596 * @return a JREF index for the Class object 597 */ 598 private static int GetObjectClass(JNIEnvironment env, int objJREF) { 599 if (traceJNI) VM.sysWrite("JNI called: GetObjectClass \n"); 600 RuntimeEntrypoints.checkJNICountDownToGC(); 601 602 try { 603 Object obj = env.getJNIRef(objJREF); 604 return env.pushJNIRef(obj.getClass()); 605 } catch (Throwable unexpected) { 606 if (traceJNI) unexpected.printStackTrace(System.err); 607 env.recordException(unexpected); 608 return 0; 609 } 610 } 611 612 /** 613 * IsInstanceOf: determine if an object is an instance of the class 614 * @param env A JREF index for the JNI environment object 615 * @param objJREF a JREF index for the object to check 616 * @param classJREF a JREF index for the class to check 617 * @return true if the object is an instance of the class 618 */ 619 private static int IsInstanceOf(JNIEnvironment env, int objJREF, int classJREF) { 620 if (traceJNI) VM.sysWrite("JNI called: IsInstanceOf \n"); 621 RuntimeEntrypoints.checkJNICountDownToGC(); 622 623 try { 624 Class<?> cls = (Class<?>) env.getJNIRef(classJREF); 625 Object obj = env.getJNIRef(objJREF); 626 if (obj == null) return 0; // null instanceof T is always false 627 RVMType RHStype = ObjectModel.getObjectType(obj); 628 RVMType LHStype = java.lang.JikesRVMSupport.getTypeForClass(cls); 629 return (LHStype == RHStype || RuntimeEntrypoints.isAssignableWith(LHStype, RHStype)) ? 1 : 0; 630 } catch (Throwable unexpected) { 631 if (traceJNI) unexpected.printStackTrace(System.err); 632 env.recordException(unexpected); 633 return 0; 634 } 635 } 636 637 /** 638 * GetMethodID: get the virtual method ID given the name and the signature 639 * @param env A JREF index for the JNI environment object 640 * @param classJREF a JREF index for the class object 641 * @param methodNameAddress a raw address to a null-terminated string in C for the method name 642 * @param methodSigAddress a raw address to a null-terminated string in C for the method signature 643 * @return id of a MethodReference 644 * @exception NoSuchMethodError if the method cannot be found 645 * @exception ExceptionInInitializerError if the class or interface static initializer fails 646 * @exception OutOfMemoryError if the system runs out of memory 647 */ 648 private static int GetMethodID(JNIEnvironment env, int classJREF, Address methodNameAddress, 649 Address methodSigAddress) { 650 if (traceJNI) VM.sysWrite("JNI called: GetMethodID \n"); 651 RuntimeEntrypoints.checkJNICountDownToGC(); 652 653 try { 654 // obtain the names as String from the native space 655 String methodString = JNIHelpers.createStringFromC(methodNameAddress); 656 Atom methodName = Atom.findOrCreateAsciiAtom(methodString); 657 String sigString = JNIHelpers.createStringFromC(methodSigAddress); 658 Atom sigName = Atom.findOrCreateAsciiAtom(sigString); 659 660 // get the target class 661 Class<?> jcls = (Class<?>) env.getJNIRef(classJREF); 662 RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls); 663 if (!type.isClassType()) { 664 env.recordException(new NoSuchMethodError()); 665 return 0; 666 } 667 668 RVMClass klass = type.asClass(); 669 if (!klass.isInitialized()) { 670 RuntimeEntrypoints.initializeClassForDynamicLink(klass); 671 } 672 673 // Find the target method 674 final RVMMethod meth; 675 if (methodString.equals("<init>")) { 676 meth = klass.findInitializerMethod(sigName); 677 } else { 678 meth = klass.findVirtualMethod(methodName, sigName); 679 } 680 681 if (meth == null) { 682 env.recordException(new NoSuchMethodError(klass + ": " + methodName + " " + sigName)); 683 return 0; 684 } 685 686 if (traceJNI) VM.sysWrite("got method " + meth + "\n"); 687 return meth.getId(); 688 } catch (Throwable unexpected) { 689 if (traceJNI) unexpected.printStackTrace(System.err); 690 env.recordException(unexpected); 691 return 0; 692 } 693 } 694 695 /** 696 * CallObjectMethod: invoke a virtual method that returns an object 697 * arguments passed using the vararg ... style 698 * NOTE: the vararg's are not visible in the method signature here; 699 * they are saved in the caller frame and the glue frame 700 * @param env A JREF index for the JNI environment object 701 * @param objJREF a JREF index for the object instance 702 * @param methodID id of a MethodReference 703 * @return the JREF index for the object returned from the method invocation 704 */ 705 private static int CallObjectMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 706 if (traceJNI) VM.sysWrite("JNI called: CallObjectMethod \n"); 707 RuntimeEntrypoints.checkJNICountDownToGC(); 708 709 try { 710 Object obj = env.getJNIRef(objJREF); 711 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, null, false); 712 return env.pushJNIRef(returnObj); 713 } catch (Throwable unexpected) { 714 if (traceJNI) unexpected.printStackTrace(System.err); 715 env.recordException(unexpected); 716 return 0; 717 } 718 } 719 720 /** 721 * CallObjectMethodV: invoke a virtual method that returns an object 722 * @param env A JREF index for the JNI environment object 723 * @param objJREF a JREF index for the object instance 724 * @param methodID id of a MethodReference 725 * @param argAddress a raw address to a variable argument list, each element is 726 * 1-word or 2-words of the appropriate type for the method invocation 727 * @return the JREF index for the object returned from the method invocation 728 */ 729 private static int CallObjectMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 730 throws Exception { 731 if (traceJNI) VM.sysWrite("JNI called: CallObjectMethodV \n"); 732 RuntimeEntrypoints.checkJNICountDownToGC(); 733 734 try { 735 Object obj = env.getJNIRef(objJREF); 736 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, null, false); 737 return env.pushJNIRef(returnObj); 738 } catch (Throwable unexpected) { 739 if (traceJNI) unexpected.printStackTrace(System.err); 740 env.recordException(unexpected); 741 return 0; 742 } 743 } 744 745 /** 746 * CallObjectMethodA: invoke a virtual method that returns an object value 747 * @param env A JREF index for the JNI environment object 748 * @param objJREF a JREF index for the object instance 749 * @param methodID id of a MethodReference 750 * @param argAddress a raw address to an array of unions in C, each element is 2-word 751 * and hold an argument of the appropriate type for the method invocation 752 * @return the JREF index for the object returned from the method invocation 753 */ 754 private static int CallObjectMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 755 throws Exception { 756 if (traceJNI) VM.sysWrite("JNI called: CallObjectMethodA \n"); 757 RuntimeEntrypoints.checkJNICountDownToGC(); 758 759 try { 760 Object obj = env.getJNIRef(objJREF); 761 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, null, false); 762 return env.pushJNIRef(returnObj); 763 } catch (Throwable unexpected) { 764 if (traceJNI) unexpected.printStackTrace(System.err); 765 env.recordException(unexpected); 766 return 0; 767 } 768 } 769 770 /** 771 * CallBooleanMethod: invoke a virtual method that returns a boolean value 772 * arguments passed using the vararg ... style 773 * NOTE: the vararg's are not visible in the method signature here; 774 * they are saved in the caller frame and the glue frame 775 * @param env A JREF index for the JNI environment object 776 * @param objJREF a JREF index for the object instance 777 * @param methodID id of a MethodReference 778 * @return the boolean value returned from the method invocation 779 */ 780 private static boolean CallBooleanMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 781 if (traceJNI) VM.sysWrite("JNI called: CallBooleanMethod \n"); 782 RuntimeEntrypoints.checkJNICountDownToGC(); 783 784 try { 785 Object obj = env.getJNIRef(objJREF); 786 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Boolean, false); 787 return Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value 788 } catch (Throwable unexpected) { 789 if (traceJNI) unexpected.printStackTrace(System.err); 790 env.recordException(unexpected); 791 return false; 792 } 793 } 794 795 /** 796 * CallBooleanMethodV: invoke a virtual method that returns a boolean value 797 * @param env A JREF index for the JNI environment object 798 * @param objJREF a JREF index for the object instance 799 * @param methodID id of a MethodReference 800 * @param argAddress a raw address to a variable argument list, each element is 801 * 1-word or 2-words of the appropriate type for the method invocation 802 * @return the boolean value returned from the method invocation 803 */ 804 private static boolean CallBooleanMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 805 throws Exception { 806 if (traceJNI) VM.sysWrite("JNI called: CallBooleanMethodV \n"); 807 RuntimeEntrypoints.checkJNICountDownToGC(); 808 809 try { 810 Object obj = env.getJNIRef(objJREF); 811 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Boolean, false); 812 return Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value 813 } catch (Throwable unexpected) { 814 if (traceJNI) unexpected.printStackTrace(System.err); 815 env.recordException(unexpected); 816 return false; 817 } 818 } 819 820 /** 821 * CallBooleanMethodA: invoke a virtual method that returns a boolean value 822 * @param env A JREF index for the JNI environment object 823 * @param objJREF a JREF index for the object instance 824 * @param methodID id of a MethodReference 825 * @param argAddress a raw address to an array of unions in C, each element is 2-word 826 * and hold an argument of the appropriate type for the method invocation 827 * @return the boolean value returned from the method invocation 828 */ 829 private static boolean CallBooleanMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 830 throws Exception { 831 if (traceJNI) VM.sysWrite("JNI called: CallBooleanMethodA \n"); 832 RuntimeEntrypoints.checkJNICountDownToGC(); 833 834 try { 835 Object obj = env.getJNIRef(objJREF); 836 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Boolean, false); 837 return Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value 838 } catch (Throwable unexpected) { 839 if (traceJNI) unexpected.printStackTrace(System.err); 840 env.recordException(unexpected); 841 return false; 842 } 843 } 844 845 /** 846 * CallByteMethod: invoke a virtual method that returns a byte value 847 * arguments passed using the vararg ... style 848 * NOTE: the vararg's are not visible in the method signature here; 849 * they are saved in the caller frame and the glue frame 850 * @param env A JREF index for the JNI environment object 851 * @param objJREF a JREF index for the object instance 852 * @param methodID id of a MethodReference 853 * @return the byte value returned from the method invocation 854 */ 855 private static byte CallByteMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 856 if (traceJNI) VM.sysWrite("JNI called: CallByteMethod \n"); 857 RuntimeEntrypoints.checkJNICountDownToGC(); 858 859 try { 860 Object obj = env.getJNIRef(objJREF); 861 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Byte, false); 862 return Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value 863 } catch (Throwable unexpected) { 864 if (traceJNI) unexpected.printStackTrace(System.err); 865 env.recordException(unexpected); 866 return 0; 867 } 868 } 869 870 /** 871 * CallByteMethodV: invoke a virtual method that returns a byte value 872 * @param env A JREF index for the JNI environment object 873 * @param objJREF a JREF index for the object instance 874 * @param methodID id of a MethodReference 875 * @param argAddress a raw address to a variable argument list, each element is 876 * 1-word or 2-words of the appropriate type for the method invocation 877 * @return the byte value returned from the method invocation 878 */ 879 private static byte CallByteMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 880 throws Exception { 881 if (traceJNI) VM.sysWrite("JNI called: CallByteMethodV \n"); 882 RuntimeEntrypoints.checkJNICountDownToGC(); 883 884 try { 885 Object obj = env.getJNIRef(objJREF); 886 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Byte, false); 887 return Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value 888 } catch (Throwable unexpected) { 889 if (traceJNI) unexpected.printStackTrace(System.err); 890 env.recordException(unexpected); 891 return 0; 892 } 893 } 894 895 /** 896 * CallByteMethodA: invoke a virtual method that returns a byte value 897 * @param env A JREF index for the JNI environment object 898 * @param objJREF a JREF index for the object instance 899 * @param methodID id of a MethodReference 900 * @param argAddress a raw address to an array of unions in C, each element is 2-word 901 * and hold an argument of the appropriate type for the method invocation 902 * @return the byte value returned from the method invocation 903 */ 904 private static byte CallByteMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 905 throws Exception { 906 if (traceJNI) VM.sysWrite("JNI called: CallByteMethodA \n"); 907 RuntimeEntrypoints.checkJNICountDownToGC(); 908 909 try { 910 Object obj = env.getJNIRef(objJREF); 911 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Byte, false); 912 return Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value 913 } catch (Throwable unexpected) { 914 if (traceJNI) unexpected.printStackTrace(System.err); 915 env.recordException(unexpected); 916 return 0; 917 } 918 } 919 920 /** 921 * CallCharMethod: invoke a virtual method that returns a char value 922 * arguments passed using the vararg ... style 923 * NOTE: the vararg's are not visible in the method signature here; 924 * they are saved in the caller frame and the glue frame 925 * @param env A JREF index for the JNI environment object 926 * @param objJREF a JREF index for the object instance 927 * @param methodID id of a MethodReference 928 * @return the char value returned from the method invocation 929 */ 930 private static char CallCharMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 931 if (traceJNI) VM.sysWrite("JNI called: CallCharMethod \n"); 932 RuntimeEntrypoints.checkJNICountDownToGC(); 933 934 try { 935 Object obj = env.getJNIRef(objJREF); 936 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Char, false); 937 return Reflection.unwrapChar(returnObj); // should be a wrapper for a char value 938 } catch (Throwable unexpected) { 939 if (traceJNI) unexpected.printStackTrace(System.err); 940 env.recordException(unexpected); 941 return 0; 942 } 943 } 944 945 /** 946 * CallCharMethodV: invoke a virtual method that returns a char value 947 * @param env A JREF index for the JNI environment object 948 * @param objJREF a JREF index for the object instance 949 * @param methodID id of a MethodReference 950 * @param argAddress a raw address to a variable argument list, each element is 951 * 1-word or 2-words of the appropriate type for the method invocation 952 * @return the char value returned from the method invocation 953 */ 954 private static char CallCharMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 955 throws Exception { 956 if (traceJNI) VM.sysWrite("JNI called: CallCharMethodV \n"); 957 RuntimeEntrypoints.checkJNICountDownToGC(); 958 959 try { 960 Object obj = env.getJNIRef(objJREF); 961 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Char, false); 962 return Reflection.unwrapChar(returnObj); // should be a wrapper for a char value 963 } catch (Throwable unexpected) { 964 if (traceJNI) unexpected.printStackTrace(System.err); 965 env.recordException(unexpected); 966 return 0; 967 } 968 } 969 970 /** 971 * CallCharMethodA: invoke a virtual method that returns a char value 972 * @param env A JREF index for the JNI environment object 973 * @param objJREF a JREF index for the object instance 974 * @param methodID id of a MethodReference 975 * @param argAddress a raw address to an array of unions in C, each element is 2-word 976 * and hold an argument of the appropriate type for the method invocation 977 * @return the char value returned from the method invocation 978 */ 979 private static char CallCharMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 980 throws Exception { 981 if (traceJNI) VM.sysWrite("JNI called: CallCharMethodA \n"); 982 RuntimeEntrypoints.checkJNICountDownToGC(); 983 984 try { 985 Object obj = env.getJNIRef(objJREF); 986 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Char, false); 987 return Reflection.unwrapChar(returnObj); // should be a wrapper for a char value 988 } catch (Throwable unexpected) { 989 if (traceJNI) unexpected.printStackTrace(System.err); 990 env.recordException(unexpected); 991 return 0; 992 } 993 } 994 995 /** 996 * CallShortMethod: invoke a virtual method that returns a short value 997 * arguments passed using the vararg ... style 998 * NOTE: the vararg's are not visible in the method signature here; 999 * they are saved in the caller frame and the glue frame 1000 * @param env A JREF index for the JNI environment object 1001 * @param objJREF a JREF index for the object instance 1002 * @param methodID id of a MethodReference 1003 * @return the short value returned from the method invocation 1004 */ 1005 private static short CallShortMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 1006 if (traceJNI) VM.sysWrite("JNI called: CallShortMethod \n"); 1007 RuntimeEntrypoints.checkJNICountDownToGC(); 1008 1009 try { 1010 Object obj = env.getJNIRef(objJREF); 1011 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Short, false); 1012 return Reflection.unwrapShort(returnObj); // should be a wrapper for a short value 1013 } catch (Throwable unexpected) { 1014 if (traceJNI) unexpected.printStackTrace(System.err); 1015 env.recordException(unexpected); 1016 return 0; 1017 } 1018 } 1019 1020 /** 1021 * CallShortMethodV: invoke a virtual method that returns a short value 1022 * @param env A JREF index for the JNI environment object 1023 * @param objJREF a JREF index for the object instance 1024 * @param methodID id of a MethodReference 1025 * @param argAddress a raw address to a variable argument list, each element is 1026 * 1-word or 2-words of the appropriate type for the method invocation 1027 * @return the short value returned from the method invocation 1028 */ 1029 private static short CallShortMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1030 throws Exception { 1031 if (traceJNI) VM.sysWrite("JNI called: CallShortMethodV \n"); 1032 RuntimeEntrypoints.checkJNICountDownToGC(); 1033 1034 try { 1035 Object obj = env.getJNIRef(objJREF); 1036 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Short, false); 1037 return Reflection.unwrapShort(returnObj); // should be a wrapper for a short value 1038 } catch (Throwable unexpected) { 1039 if (traceJNI) unexpected.printStackTrace(System.err); 1040 env.recordException(unexpected); 1041 return 0; 1042 } 1043 } 1044 1045 /** 1046 * CallShortMethodA: invoke a virtual method that returns a short value 1047 * @param env A JREF index for the JNI environment object 1048 * @param objJREF a JREF index for the object instance 1049 * @param methodID id of a MethodReference 1050 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1051 * and hold an argument of the appropriate type for the method invocation 1052 * @return the short value returned from the method invocation 1053 */ 1054 private static short CallShortMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1055 throws Exception { 1056 if (traceJNI) VM.sysWrite("JNI called: CallShortMethodA \n"); 1057 RuntimeEntrypoints.checkJNICountDownToGC(); 1058 1059 try { 1060 Object obj = env.getJNIRef(objJREF); 1061 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Short, false); 1062 return Reflection.unwrapShort(returnObj); // should be a wrapper for a short value 1063 } catch (Throwable unexpected) { 1064 if (traceJNI) unexpected.printStackTrace(System.err); 1065 env.recordException(unexpected); 1066 return 0; 1067 } 1068 } 1069 1070 /** 1071 * CallIntMethod: invoke a virtual method that returns a int value 1072 * arguments passed using the vararg ... style 1073 * NOTE: the vararg's are not visible in the method signature here; 1074 * they are saved in the caller frame and the glue frame 1075 * @param env A JREF index for the JNI environment object 1076 * @param objJREF a JREF index for the object instance 1077 * @param methodID id of a MethodReference 1078 * @return the int value returned from the method invocation 1079 */ 1080 private static int CallIntMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 1081 if (traceJNI) VM.sysWrite("JNI called: CallIntMethod \n"); 1082 RuntimeEntrypoints.checkJNICountDownToGC(); 1083 1084 try { 1085 Object obj = env.getJNIRef(objJREF); 1086 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Int, false); 1087 return Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value 1088 } catch (Throwable unexpected) { 1089 if (traceJNI) unexpected.printStackTrace(System.err); 1090 env.recordException(unexpected); 1091 return 0; 1092 } 1093 } 1094 1095 /** 1096 * CallIntMethodV: invoke a virtual method that returns an int value 1097 * @param env A JREF index for the JNI environment object 1098 * @param objJREF a JREF index for the object instance 1099 * @param methodID id of a MethodReference 1100 * @param argAddress a raw address to a variable argument list, each element is 1101 * 1-word or 2-words of the appropriate type for the method invocation 1102 * @return the int value returned from the method invocation 1103 */ 1104 private static int CallIntMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1105 throws Exception { 1106 if (traceJNI) VM.sysWrite("JNI called: CallIntMethodV \n"); 1107 RuntimeEntrypoints.checkJNICountDownToGC(); 1108 1109 try { 1110 Object obj = env.getJNIRef(objJREF); 1111 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Int, false); 1112 return Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value 1113 } catch (Throwable unexpected) { 1114 if (traceJNI) unexpected.printStackTrace(System.err); 1115 env.recordException(unexpected); 1116 return 0; 1117 } 1118 } 1119 1120 /** 1121 * CallIntMethodA: invoke a virtual method that returns an integer value 1122 * @param env A JREF index for the JNI environment object 1123 * @param objJREF a JREF index for the object instance 1124 * @param methodID id of a MethodReference 1125 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1126 * and hold an argument of the appropriate type for the method invocation 1127 * @return the integer value returned from the method invocation 1128 */ 1129 private static int CallIntMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1130 throws Exception { 1131 if (traceJNI) VM.sysWrite("JNI called: CallIntMethodA \n"); 1132 RuntimeEntrypoints.checkJNICountDownToGC(); 1133 1134 try { 1135 Object obj = env.getJNIRef(objJREF); 1136 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Int, false); 1137 return Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value 1138 } catch (Throwable unexpected) { 1139 if (traceJNI) unexpected.printStackTrace(System.err); 1140 env.recordException(unexpected); 1141 return 0; 1142 } 1143 } 1144 1145 /** 1146 * CallLongMethod: invoke a virtual method that returns a long value 1147 * arguments passed using the vararg ... style 1148 * NOTE: the vararg's are not visible in the method signature here; 1149 * they are saved in the caller frame and the glue frame 1150 * @param env A JREF index for the JNI environment object 1151 * @param objJREF a JREF index for the object instance 1152 * @param methodID id of a MethodReference 1153 * @return the long value returned from the method invocation 1154 */ 1155 private static long CallLongMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 1156 if (traceJNI) VM.sysWrite("JNI called: CallLongMethod \n"); 1157 RuntimeEntrypoints.checkJNICountDownToGC(); 1158 1159 try { 1160 Object obj = env.getJNIRef(objJREF); 1161 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Long, false); 1162 return Reflection.unwrapLong(returnObj); // should be a wrapper for a long value 1163 } catch (Throwable unexpected) { 1164 if (traceJNI) unexpected.printStackTrace(System.err); 1165 env.recordException(unexpected); 1166 return 0; 1167 } 1168 } 1169 1170 /** 1171 * CallLongMethodV: invoke a virtual method that returns a long value 1172 * @param env A JREF index for the JNI environment object 1173 * @param objJREF a JREF index for the object instance 1174 * @param methodID id of a MethodReference 1175 * @param argAddress a raw address to a variable argument list, each element is 1176 * 1-word or 2-words of the appropriate type for the method invocation 1177 * @return the long value returned from the method invocation 1178 */ 1179 private static long CallLongMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1180 throws Exception { 1181 if (traceJNI) VM.sysWrite("JNI called: CallLongMethodV \n"); 1182 RuntimeEntrypoints.checkJNICountDownToGC(); 1183 1184 try { 1185 Object obj = env.getJNIRef(objJREF); 1186 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Long, false); 1187 return Reflection.unwrapLong(returnObj); // should be a wrapper for a long value 1188 } catch (Throwable unexpected) { 1189 if (traceJNI) unexpected.printStackTrace(System.err); 1190 env.recordException(unexpected); 1191 return 0; 1192 } 1193 } 1194 1195 /** 1196 * CallLongMethodA: invoke a virtual method that returns a long value 1197 * @param env A JREF index for the JNI environment object 1198 * @param objJREF a JREF index for the object instance 1199 * @param methodID id of a MethodReference 1200 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1201 * and hold an argument of the appropriate type for the method invocation 1202 * @return the long value returned from the method invocation 1203 */ 1204 private static long CallLongMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1205 throws Exception { 1206 if (traceJNI) VM.sysWrite("JNI called: CallLongMethodA \n"); 1207 RuntimeEntrypoints.checkJNICountDownToGC(); 1208 1209 try { 1210 Object obj = env.getJNIRef(objJREF); 1211 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Long, false); 1212 return Reflection.unwrapLong(returnObj); // should be a wrapper for a long value 1213 } catch (Throwable unexpected) { 1214 if (traceJNI) unexpected.printStackTrace(System.err); 1215 env.recordException(unexpected); 1216 return 0; 1217 } 1218 } 1219 1220 /** 1221 * CallFloatMethod: invoke a virtual method that returns a float value 1222 * arguments passed using the vararg ... style 1223 * NOTE: the vararg's are not visible in the method signature here; 1224 * they are saved in the caller frame and the glue frame 1225 * @param env A JREF index for the JNI environment object 1226 * @param objJREF a JREF index for the object instance 1227 * @param methodID id of a MethodReference 1228 * @return the float value returned from the method invocation 1229 */ 1230 private static float CallFloatMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 1231 if (traceJNI) VM.sysWrite("JNI called: CallFloatMethod \n"); 1232 RuntimeEntrypoints.checkJNICountDownToGC(); 1233 1234 try { 1235 Object obj = env.getJNIRef(objJREF); 1236 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Float, false); 1237 return Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value 1238 } catch (Throwable unexpected) { 1239 if (traceJNI) unexpected.printStackTrace(System.err); 1240 env.recordException(unexpected); 1241 return 0; 1242 } 1243 } 1244 1245 /** 1246 * CallFloatMethodV: invoke a virtual method that returns a float value 1247 * @param env A JREF index for the JNI environment object 1248 * @param objJREF a JREF index for the object instance 1249 * @param methodID id of a MethodReference 1250 * @param argAddress a raw address to a variable argument list, each element is 1251 * 1-word or 2-words of the appropriate type for the method invocation 1252 * @return the float value returned from the method invocation 1253 */ 1254 private static float CallFloatMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1255 throws Exception { 1256 if (traceJNI) VM.sysWrite("JNI called: CallFloatMethodV \n"); 1257 RuntimeEntrypoints.checkJNICountDownToGC(); 1258 1259 try { 1260 Object obj = env.getJNIRef(objJREF); 1261 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Float, false); 1262 return Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value 1263 } catch (Throwable unexpected) { 1264 if (traceJNI) unexpected.printStackTrace(System.err); 1265 env.recordException(unexpected); 1266 return 0; 1267 } 1268 } 1269 1270 /** 1271 * CallFloatMethodA: invoke a virtual method that returns a float value 1272 * @param env A JREF index for the JNI environment object 1273 * @param objJREF a JREF index for the object instance 1274 * @param methodID id of a MethodReference 1275 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1276 * and hold an argument of the appropriate type for the method invocation 1277 * @return the float value returned from the method invocation 1278 */ 1279 private static float CallFloatMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1280 throws Exception { 1281 if (traceJNI) VM.sysWrite("JNI called: CallFloatMethodA \n"); 1282 RuntimeEntrypoints.checkJNICountDownToGC(); 1283 1284 try { 1285 Object obj = env.getJNIRef(objJREF); 1286 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Float, false); 1287 return Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value 1288 } catch (Throwable unexpected) { 1289 if (traceJNI) unexpected.printStackTrace(System.err); 1290 env.recordException(unexpected); 1291 return 0; 1292 } 1293 } 1294 1295 /** 1296 * CallDoubleMethod: invoke a virtual method that returns a double value 1297 * arguments passed using the vararg ... style 1298 * NOTE: the vararg's are not visible in the method signature here; 1299 * they are saved in the caller frame and the glue frame 1300 * @param env A JREF index for the JNI environment object 1301 * @param objJREF a JREF index for the object instance 1302 * @param methodID id of a MethodReference 1303 * @return the double value returned from the method invocation 1304 */ 1305 private static double CallDoubleMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 1306 if (traceJNI) VM.sysWrite("JNI called: CallDoubleMethod \n"); 1307 RuntimeEntrypoints.checkJNICountDownToGC(); 1308 1309 try { 1310 Object obj = env.getJNIRef(objJREF); 1311 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Double, false); 1312 return Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value 1313 } catch (Throwable unexpected) { 1314 if (traceJNI) unexpected.printStackTrace(System.err); 1315 env.recordException(unexpected); 1316 return 0; 1317 } 1318 } 1319 1320 /** 1321 * CallDoubleMethodV: invoke a virtual method that returns a double value 1322 * @param env A JREF index for the JNI environment object 1323 * @param objJREF a JREF index for the object instance 1324 * @param methodID id of a MethodReference 1325 * @param argAddress a raw address to a variable argument list, each element is 1326 * 1-word or 2-words of the appropriate type for the method invocation 1327 * @return the double value returned from the method invocation 1328 */ 1329 private static double CallDoubleMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1330 throws Exception { 1331 if (traceJNI) VM.sysWrite("JNI called: CallDoubleMethodV \n"); 1332 RuntimeEntrypoints.checkJNICountDownToGC(); 1333 1334 try { 1335 Object obj = env.getJNIRef(objJREF); 1336 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Double, false); 1337 return Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value 1338 } catch (Throwable unexpected) { 1339 if (traceJNI) unexpected.printStackTrace(System.err); 1340 env.recordException(unexpected); 1341 return 0; 1342 } 1343 } 1344 1345 /** 1346 * CallDoubleMethodA: invoke a virtual method that returns a double value 1347 * @param env A JREF index for the JNI environment object 1348 * @param objJREF a JREF index for the object instance 1349 * @param methodID id of a MethodReference 1350 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1351 * and hold an argument of the appropriate type for the method invocation 1352 * @return the double value returned from the method invocation 1353 */ 1354 private static double CallDoubleMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1355 throws Exception { 1356 if (traceJNI) VM.sysWrite("JNI called: CallDoubleMethodA \n"); 1357 RuntimeEntrypoints.checkJNICountDownToGC(); 1358 1359 try { 1360 Object obj = env.getJNIRef(objJREF); 1361 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Double, false); 1362 return Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value 1363 } catch (Throwable unexpected) { 1364 if (traceJNI) unexpected.printStackTrace(System.err); 1365 env.recordException(unexpected); 1366 return 0; 1367 } 1368 } 1369 1370 /** 1371 * CallVoidMethod: invoke a virtual method that returns a void value 1372 * arguments passed using the vararg ... style 1373 * NOTE: the vararg's are not visible in the method signature here; 1374 * they are saved in the caller frame and the glue frame 1375 * @param env A JREF index for the JNI environment object 1376 * @param objJREF a JREF index for the object instance 1377 * @param methodID id of a MethodReference 1378 */ 1379 private static void CallVoidMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception { 1380 if (traceJNI) VM.sysWrite("JNI called: CallVoidMethod \n"); 1381 RuntimeEntrypoints.checkJNICountDownToGC(); 1382 1383 try { 1384 Object obj = env.getJNIRef(objJREF); 1385 JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Void, false); 1386 } catch (Throwable unexpected) { 1387 if (traceJNI) unexpected.printStackTrace(System.err); 1388 env.recordException(unexpected); 1389 } 1390 } 1391 1392 /** 1393 * CallVoidMethodV: invoke a virtual method that returns void 1394 * @param env A JREF index for the JNI environment object 1395 * @param objJREF a JREF index for the object instance 1396 * @param methodID id of a MethodReference 1397 * @param argAddress a raw address to a variable argument list, each element is 1398 * 1-word or 2-words of the appropriate type for the method invocation 1399 */ 1400 private static void CallVoidMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1401 throws Exception { 1402 if (traceJNI) VM.sysWrite("JNI called: CallVoidMethodV \n"); 1403 RuntimeEntrypoints.checkJNICountDownToGC(); 1404 1405 try { 1406 Object obj = env.getJNIRef(objJREF); 1407 JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Void, false); 1408 } catch (Throwable unexpected) { 1409 if (traceJNI) unexpected.printStackTrace(System.err); 1410 env.recordException(unexpected); 1411 } 1412 } 1413 1414 /** 1415 * CallVoidMethodA: invoke a virtual method that returns void 1416 * @param env A JREF index for the JNI environment object 1417 * @param objJREF a JREF index for the object instance 1418 * @param methodID id of a MethodReference 1419 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1420 * and hold an argument of the appropriate type for the method invocation 1421 */ 1422 private static void CallVoidMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress) 1423 throws Exception { 1424 if (traceJNI) VM.sysWrite("JNI called: CallVoidMethodA \n"); 1425 RuntimeEntrypoints.checkJNICountDownToGC(); 1426 1427 try { 1428 Object obj = env.getJNIRef(objJREF); 1429 JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Void, false); 1430 } catch (Throwable unexpected) { 1431 if (traceJNI) unexpected.printStackTrace(System.err); 1432 env.recordException(unexpected); 1433 } 1434 } 1435 1436 /** 1437 * CallNonvirtualObjectMethod: invoke a virtual method that returns an object 1438 * arguments passed using the vararg ... style 1439 * NOTE: the vararg's are not visible in the method signature here; 1440 * they are saved in the caller frame and the glue frame 1441 * @param env A JREF index for the JNI environment object 1442 * @param objJREF a JREF index for the object instance 1443 * @param classJREF a JREF index for the class object that declares this method 1444 * @param methodID id of a MethodReference 1445 * @return the JREF index for the object returned from the method invocation 1446 */ 1447 private static int CallNonvirtualObjectMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 1448 throws Exception { 1449 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualObjectMethod \n"); 1450 RuntimeEntrypoints.checkJNICountDownToGC(); 1451 1452 try { 1453 Object obj = env.getJNIRef(objJREF); 1454 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, null, true); 1455 return env.pushJNIRef(returnObj); 1456 } catch (Throwable unexpected) { 1457 if (traceJNI) unexpected.printStackTrace(System.err); 1458 env.recordException(unexpected); 1459 return 0; 1460 } 1461 } 1462 1463 /** 1464 * CallNonvirtualObjectMethodV: invoke a virtual method that returns an object 1465 * @param env A JREF index for the JNI environment object 1466 * @param objJREF a JREF index for the object instance 1467 * @param classJREF a JREF index for the class object that declares this method 1468 * @param methodID id of a MethodReference 1469 * @param argAddress a raw address to a variable argument list, each element is 1470 * 1-word or 2-words of the appropriate type for the method invocation 1471 * @return the JREF index for the object returned from the method invocation 1472 */ 1473 private static int CallNonvirtualObjectMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1474 Address argAddress) throws Exception { 1475 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualObjectMethodV \n"); 1476 RuntimeEntrypoints.checkJNICountDownToGC(); 1477 1478 try { 1479 Object obj = env.getJNIRef(objJREF); 1480 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, null, true); 1481 return env.pushJNIRef(returnObj); 1482 } catch (Throwable unexpected) { 1483 if (traceJNI) unexpected.printStackTrace(System.err); 1484 env.recordException(unexpected); 1485 return 0; 1486 } 1487 } 1488 1489 /** 1490 * CallNonvirtualNonvirtualObjectMethodA: invoke a virtual method that returns an object value 1491 * @param env A JREF index for the JNI environment object 1492 * @param objJREF a JREF index for the object instance 1493 * @param classJREF a JREF index for the class object that declares this method 1494 * @param methodID id of a MethodReference 1495 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1496 * and hold an argument of the appropriate type for the method invocation 1497 * @return the JREF index for the object returned from the method invocation 1498 */ 1499 private static int CallNonvirtualObjectMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1500 Address argAddress) throws Exception { 1501 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualObjectMethodA \n"); 1502 RuntimeEntrypoints.checkJNICountDownToGC(); 1503 1504 try { 1505 Object obj = env.getJNIRef(objJREF); 1506 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, null, true); 1507 return env.pushJNIRef(returnObj); 1508 } catch (Throwable unexpected) { 1509 if (traceJNI) unexpected.printStackTrace(System.err); 1510 env.recordException(unexpected); 1511 return 0; 1512 } 1513 } 1514 1515 /** 1516 * CallNonvirtualBooleanMethod: invoke a virtual method that returns a boolean value 1517 * arguments passed using the vararg ... style 1518 * NOTE: the vararg's are not visible in the method signature here; 1519 * they are saved in the caller frame and the glue frame 1520 * @param env A JREF index for the JNI environment object 1521 * @param objJREF a JREF index for the object instance 1522 * @param classJREF a JREF index for the class object that declares this method 1523 * @param methodID id of a MethodReference 1524 * @return the boolean value returned from the method invocation 1525 */ 1526 private static boolean CallNonvirtualBooleanMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 1527 throws Exception { 1528 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualBooleanMethod \n"); 1529 RuntimeEntrypoints.checkJNICountDownToGC(); 1530 1531 try { 1532 Object obj = env.getJNIRef(objJREF); 1533 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Boolean, true); 1534 return Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value 1535 } catch (Throwable unexpected) { 1536 if (traceJNI) unexpected.printStackTrace(System.err); 1537 env.recordException(unexpected); 1538 return false; 1539 } 1540 } 1541 1542 /** 1543 * CallNonvirtualBooleanMethodV: invoke a virtual method that returns a boolean value 1544 * @param env A JREF index for the JNI environment object 1545 * @param objJREF a JREF index for the object instance 1546 * @param classJREF a JREF index for the class object that declares this method 1547 * @param methodID id of a MethodReference 1548 * @param argAddress a raw address to a variable argument list, each element is 1549 * 1-word or 2-words of the appropriate type for the method invocation 1550 * @return the boolean value returned from the method invocation 1551 */ 1552 private static boolean CallNonvirtualBooleanMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1553 Address argAddress) throws Exception { 1554 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualBooleanMethodV \n"); 1555 RuntimeEntrypoints.checkJNICountDownToGC(); 1556 1557 try { 1558 Object obj = env.getJNIRef(objJREF); 1559 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Boolean, true); 1560 return Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value 1561 } catch (Throwable unexpected) { 1562 if (traceJNI) unexpected.printStackTrace(System.err); 1563 env.recordException(unexpected); 1564 return false; 1565 } 1566 } 1567 1568 /** 1569 * CallNonvirtualBooleanMethodA: invoke a virtual method that returns a boolean value 1570 * @param env A JREF index for the JNI environment object 1571 * @param objJREF a JREF index for the object instance 1572 * @param classJREF a JREF index for the class object that declares this method 1573 * @param methodID id of a MethodReference 1574 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1575 * and hold an argument of the appropriate type for the method invocation 1576 * @return the boolean value returned from the method invocation 1577 */ 1578 private static boolean CallNonvirtualBooleanMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1579 Address argAddress) throws Exception { 1580 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualBooleanMethodA \n"); 1581 RuntimeEntrypoints.checkJNICountDownToGC(); 1582 1583 try { 1584 Object obj = env.getJNIRef(objJREF); 1585 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Boolean, true); 1586 return Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value 1587 } catch (Throwable unexpected) { 1588 if (traceJNI) unexpected.printStackTrace(System.err); 1589 env.recordException(unexpected); 1590 return false; 1591 } 1592 } 1593 1594 /** 1595 * CallNonvirtualByteMethod: invoke a virtual method that returns a byte value 1596 * arguments passed using the vararg ... style 1597 * NOTE: the vararg's are not visible in the method signature here; 1598 * they are saved in the caller frame and the glue frame 1599 * @param env A JREF index for the JNI environment object 1600 * @param objJREF a JREF index for the object instance 1601 * @param classJREF a JREF index for the class object that declares this method 1602 * @param methodID id of a MethodReference 1603 * @return the byte value returned from the method invocation 1604 */ 1605 private static byte CallNonvirtualByteMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 1606 throws Exception { 1607 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualByteMethod \n"); 1608 RuntimeEntrypoints.checkJNICountDownToGC(); 1609 1610 try { 1611 Object obj = env.getJNIRef(objJREF); 1612 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Byte, true); 1613 return Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value 1614 } catch (Throwable unexpected) { 1615 if (traceJNI) unexpected.printStackTrace(System.err); 1616 env.recordException(unexpected); 1617 return 0; 1618 } 1619 } 1620 1621 /** 1622 * CallNonvirtualByteMethodV: invoke a virtual method that returns a byte value 1623 * @param env A JREF index for the JNI environment object 1624 * @param objJREF a JREF index for the object instance 1625 * @param methodID id of a MethodReference 1626 * @param classJREF a JREF index for the class object that declares this method 1627 * @param argAddress a raw address to a variable argument list, each element is 1628 * 1-word or 2-words of the appropriate type for the method invocation 1629 * @return the byte value returned from the method invocation 1630 */ 1631 private static byte CallNonvirtualByteMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1632 Address argAddress) throws Exception { 1633 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualByteMethodV \n"); 1634 RuntimeEntrypoints.checkJNICountDownToGC(); 1635 1636 try { 1637 Object obj = env.getJNIRef(objJREF); 1638 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Byte, true); 1639 return Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value 1640 } catch (Throwable unexpected) { 1641 if (traceJNI) unexpected.printStackTrace(System.err); 1642 env.recordException(unexpected); 1643 return 0; 1644 } 1645 } 1646 1647 /** 1648 * CallNonvirtualByteMethodA: invoke a virtual method that returns a byte value 1649 * @param env A JREF index for the JNI environment object 1650 * @param objJREF a JREF index for the object instance 1651 * @param methodID id of a MethodReference 1652 * @param classJREF a JREF index for the class object that declares this method 1653 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1654 * and hold an argument of the appropriate type for the method invocation 1655 * @return the byte value returned from the method invocation 1656 */ 1657 private static byte CallNonvirtualByteMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1658 Address argAddress) throws Exception { 1659 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualByteMethodA \n"); 1660 RuntimeEntrypoints.checkJNICountDownToGC(); 1661 1662 try { 1663 Object obj = env.getJNIRef(objJREF); 1664 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Byte, true); 1665 return Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value 1666 } catch (Throwable unexpected) { 1667 if (traceJNI) unexpected.printStackTrace(System.err); 1668 env.recordException(unexpected); 1669 return 0; 1670 } 1671 } 1672 1673 /** 1674 * CallNonvirtualCharMethod: invoke a virtual method that returns a char value 1675 * arguments passed using the vararg ... style 1676 * NOTE: the vararg's are not visible in the method signature here; 1677 * they are saved in the caller frame and the glue frame 1678 * @param env A JREF index for the JNI environment object 1679 * @param objJREF a JREF index for the object instance 1680 * @param classJREF a JREF index for the class object that declares this method 1681 * @param methodID id of a MethodReference 1682 * @return the char value returned from the method invocation 1683 */ 1684 private static char CallNonvirtualCharMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 1685 throws Exception { 1686 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualCharMethod \n"); 1687 RuntimeEntrypoints.checkJNICountDownToGC(); 1688 1689 try { 1690 Object obj = env.getJNIRef(objJREF); 1691 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Char, true); 1692 return Reflection.unwrapChar(returnObj); // should be a wrapper for a char value 1693 } catch (Throwable unexpected) { 1694 if (traceJNI) unexpected.printStackTrace(System.err); 1695 env.recordException(unexpected); 1696 return 0; 1697 } 1698 } 1699 1700 /** 1701 * CallNonvirtualCharMethodV: invoke a virtual method that returns a char value 1702 * @param env A JREF index for the JNI environment object 1703 * @param objJREF a JREF index for the object instance 1704 * @param classJREF a JREF index for the class object that declares this method 1705 * @param methodID id of a MethodReference 1706 * @param argAddress a raw address to a variable argument list, each element is 1707 * 1-word or 2-words of the appropriate type for the method invocation 1708 * @return the char value returned from the method invocation 1709 */ 1710 private static char CallNonvirtualCharMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1711 Address argAddress) throws Exception { 1712 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualCharMethodV \n"); 1713 RuntimeEntrypoints.checkJNICountDownToGC(); 1714 1715 try { 1716 Object obj = env.getJNIRef(objJREF); 1717 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Char, true); 1718 return Reflection.unwrapChar(returnObj); // should be a wrapper for a char value 1719 } catch (Throwable unexpected) { 1720 if (traceJNI) unexpected.printStackTrace(System.err); 1721 env.recordException(unexpected); 1722 return 0; 1723 } 1724 } 1725 1726 /** 1727 * CallNonvirtualCharMethodA: invoke a virtual method that returns a char value 1728 * @param env A JREF index for the JNI environment object 1729 * @param objJREF a JREF index for the object instance 1730 * @param classJREF a JREF index for the class object that declares this method 1731 * @param methodID id of a MethodReference 1732 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1733 * and hold an argument of the appropriate type for the method invocation 1734 * @return the char value returned from the method invocation 1735 */ 1736 private static char CallNonvirtualCharMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1737 Address argAddress) throws Exception { 1738 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualCharMethodA \n"); 1739 RuntimeEntrypoints.checkJNICountDownToGC(); 1740 1741 try { 1742 Object obj = env.getJNIRef(objJREF); 1743 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Char, true); 1744 return Reflection.unwrapChar(returnObj); // should be a wrapper for a char value 1745 } catch (Throwable unexpected) { 1746 if (traceJNI) unexpected.printStackTrace(System.err); 1747 env.recordException(unexpected); 1748 return 0; 1749 } 1750 } 1751 1752 /** 1753 * CallNonvirtualShortMethod: invoke a virtual method that returns a short value 1754 * arguments passed using the vararg ... style 1755 * NOTE: the vararg's are not visible in the method signature here; 1756 * they are saved in the caller frame and the glue frame 1757 * @param env A JREF index for the JNI environment object 1758 * @param objJREF a JREF index for the object instance 1759 * @param classJREF a JREF index for the class object that declares this method 1760 * @param methodID id of a MethodReference 1761 * @return the short value returned from the method invocation 1762 */ 1763 private static short CallNonvirtualShortMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 1764 throws Exception { 1765 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualShortMethod \n"); 1766 RuntimeEntrypoints.checkJNICountDownToGC(); 1767 1768 try { 1769 Object obj = env.getJNIRef(objJREF); 1770 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Short, true); 1771 return Reflection.unwrapShort(returnObj); // should be a wrapper for a short value 1772 } catch (Throwable unexpected) { 1773 if (traceJNI) unexpected.printStackTrace(System.err); 1774 env.recordException(unexpected); 1775 return 0; 1776 } 1777 } 1778 1779 /** 1780 * CallNonvirtualShortMethodV: invoke a virtual method that returns a short value 1781 * @param env A JREF index for the JNI environment object 1782 * @param objJREF a JREF index for the object instance 1783 * @param classJREF a JREF index for the class object that declares this method 1784 * @param methodID id of a MethodReference 1785 * @param argAddress a raw address to a variable argument list, each element is 1786 * 1-word or 2-words of the appropriate type for the method invocation 1787 * @return the short value returned from the method invocation 1788 */ 1789 private static short CallNonvirtualShortMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1790 Address argAddress) throws Exception { 1791 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualShortMethodV \n"); 1792 RuntimeEntrypoints.checkJNICountDownToGC(); 1793 1794 try { 1795 Object obj = env.getJNIRef(objJREF); 1796 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Short, true); 1797 return Reflection.unwrapShort(returnObj); // should be a wrapper for a short value 1798 } catch (Throwable unexpected) { 1799 if (traceJNI) unexpected.printStackTrace(System.err); 1800 env.recordException(unexpected); 1801 return 0; 1802 } 1803 } 1804 1805 /** 1806 * CallNonvirtualShortMethodA: invoke a virtual method that returns a short value 1807 * @param env A JREF index for the JNI environment object 1808 * @param objJREF a JREF index for the object instance 1809 * @param classJREF a JREF index for the class object that declares this method 1810 * @param methodID id of a MethodReference 1811 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1812 * and hold an argument of the appropriate type for the method invocation 1813 * @return the short value returned from the method invocation 1814 */ 1815 private static short CallNonvirtualShortMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1816 Address argAddress) throws Exception { 1817 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualShortMethodA \n"); 1818 RuntimeEntrypoints.checkJNICountDownToGC(); 1819 1820 try { 1821 Object obj = env.getJNIRef(objJREF); 1822 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Short, true); 1823 return Reflection.unwrapShort(returnObj); // should be a wrapper for a short value 1824 } catch (Throwable unexpected) { 1825 if (traceJNI) unexpected.printStackTrace(System.err); 1826 env.recordException(unexpected); 1827 return 0; 1828 } 1829 } 1830 1831 /** 1832 * CallNonvirtualIntMethod: invoke a virtual method that returns a int value 1833 * arguments passed using the vararg ... style 1834 * NOTE: the vararg's are not visible in the method signature here; 1835 * they are saved in the caller frame and the glue frame 1836 * @param env A JREF index for the JNI environment object 1837 * @param objJREF a JREF index for the object instance 1838 * @param classJREF a JREF index for the class object that declares this method 1839 * @param methodID id of a MethodReference 1840 * @return the int value returned from the method invocation 1841 */ 1842 private static int CallNonvirtualIntMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 1843 throws Exception { 1844 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualIntMethod \n"); 1845 RuntimeEntrypoints.checkJNICountDownToGC(); 1846 1847 try { 1848 Object obj = env.getJNIRef(objJREF); 1849 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Int, true); 1850 return Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value 1851 } catch (Throwable unexpected) { 1852 if (traceJNI) unexpected.printStackTrace(System.err); 1853 env.recordException(unexpected); 1854 return 0; 1855 } 1856 } 1857 1858 /** 1859 * CallNonvirtualIntMethodV: invoke a virtual method that returns an int value 1860 * @param env A JREF index for the JNI environment object 1861 * @param objJREF a JREF index for the object instance 1862 * @param classJREF a JREF index for the class object that declares this method 1863 * @param methodID id of a MethodReference 1864 * @param argAddress a raw address to a variable argument list, each element is 1865 * 1-word or 2-words of the appropriate type for the method invocation 1866 * @return the int value returned from the method invocation 1867 */ 1868 private static int CallNonvirtualIntMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1869 Address argAddress) throws Exception { 1870 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualIntMethodV \n"); 1871 RuntimeEntrypoints.checkJNICountDownToGC(); 1872 1873 try { 1874 Object obj = env.getJNIRef(objJREF); 1875 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Int, true); 1876 return Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value 1877 } catch (Throwable unexpected) { 1878 if (traceJNI) unexpected.printStackTrace(System.err); 1879 env.recordException(unexpected); 1880 return 0; 1881 } 1882 } 1883 1884 /** 1885 * CallNonvirtualIntMethodA: invoke a virtual method that returns an integer value 1886 * @param env A JREF index for the JNI environment object 1887 * @param objJREF a JREF index for the object instance 1888 * @param classJREF a JREF index for the class object that declares this method 1889 * @param methodID id of a MethodReference 1890 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1891 * and hold an argument of the appropriate type for the method invocation 1892 * @return the integer value returned from the method invocation 1893 */ 1894 private static int CallNonvirtualIntMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1895 Address argAddress) throws Exception { 1896 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualIntMethodA \n"); 1897 RuntimeEntrypoints.checkJNICountDownToGC(); 1898 1899 try { 1900 Object obj = env.getJNIRef(objJREF); 1901 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Int, true); 1902 return Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value 1903 } catch (Throwable unexpected) { 1904 if (traceJNI) unexpected.printStackTrace(System.err); 1905 env.recordException(unexpected); 1906 return 0; 1907 } 1908 } 1909 1910 /** 1911 * CallNonvirtualLongMethod: invoke a virtual method that returns a long value 1912 * arguments passed using the vararg ... style 1913 * NOTE: the vararg's are not visible in the method signature here; 1914 * they are saved in the caller frame and the glue frame 1915 * @param env A JREF index for the JNI environment object 1916 * @param objJREF a JREF index for the object instance 1917 * @param classJREF a JREF index for the class object that declares this method 1918 * @param methodID id of a MethodReference 1919 * @return the long value returned from the method invocation 1920 */ 1921 private static long CallNonvirtualLongMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 1922 throws Exception { 1923 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualLongMethod \n"); 1924 RuntimeEntrypoints.checkJNICountDownToGC(); 1925 1926 try { 1927 Object obj = env.getJNIRef(objJREF); 1928 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Long, true); 1929 return Reflection.unwrapLong(returnObj); // should be a wrapper for a long value 1930 } catch (Throwable unexpected) { 1931 if (traceJNI) unexpected.printStackTrace(System.err); 1932 env.recordException(unexpected); 1933 return 0; 1934 } 1935 } 1936 1937 /** 1938 * CallNonvirtualLongMethodV: invoke a virtual method that returns a long value 1939 * @param env A JREF index for the JNI environment object 1940 * @param objJREF a JREF index for the object instance 1941 * @param classJREF a JREF index for the class object that declares this method 1942 * @param methodID id of a MethodReference 1943 * @param argAddress a raw address to a variable argument list, each element is 1944 * 1-word or 2-words of the appropriate type for the method invocation 1945 * @return the long value returned from the method invocation 1946 */ 1947 private static long CallNonvirtualLongMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1948 Address argAddress) throws Exception { 1949 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualLongMethodV \n"); 1950 RuntimeEntrypoints.checkJNICountDownToGC(); 1951 1952 try { 1953 Object obj = env.getJNIRef(objJREF); 1954 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Long, true); 1955 return Reflection.unwrapLong(returnObj); // should be a wrapper for a long value 1956 } catch (Throwable unexpected) { 1957 if (traceJNI) unexpected.printStackTrace(System.err); 1958 env.recordException(unexpected); 1959 return 0; 1960 } 1961 } 1962 1963 /** 1964 * CallNonvirtualLongMethodA: invoke a virtual method that returns a long value 1965 * @param env A JREF index for the JNI environment object 1966 * @param objJREF a JREF index for the object instance 1967 * @param classJREF a JREF index for the class object that declares this method 1968 * @param methodID id of a MethodReference 1969 * @param argAddress a raw address to an array of unions in C, each element is 2-word 1970 * and hold an argument of the appropriate type for the method invocation 1971 * @return the long value returned from the method invocation 1972 */ 1973 private static long CallNonvirtualLongMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 1974 Address argAddress) throws Exception { 1975 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualLongMethodA \n"); 1976 RuntimeEntrypoints.checkJNICountDownToGC(); 1977 1978 try { 1979 Object obj = env.getJNIRef(objJREF); 1980 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Long, true); 1981 return Reflection.unwrapLong(returnObj); // should be a wrapper for a long value 1982 } catch (Throwable unexpected) { 1983 if (traceJNI) unexpected.printStackTrace(System.err); 1984 env.recordException(unexpected); 1985 return 0; 1986 } 1987 } 1988 1989 /** 1990 * CallNonvirtualFloatMethod: invoke a virtual method that returns a float value 1991 * arguments passed using the vararg ... style 1992 * NOTE: the vararg's are not visible in the method signature here; 1993 * they are saved in the caller frame and the glue frame 1994 * @param env A JREF index for the JNI environment object 1995 * @param objJREF a JREF index for the object instance 1996 * @param classJREF a JREF index for the class object that declares this method 1997 * @param methodID id of a MethodReference 1998 * @return the float value returned from the method invocation 1999 */ 2000 private static float CallNonvirtualFloatMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 2001 throws Exception { 2002 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualFloatMethod \n"); 2003 RuntimeEntrypoints.checkJNICountDownToGC(); 2004 2005 try { 2006 Object obj = env.getJNIRef(objJREF); 2007 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Float, true); 2008 return Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value 2009 } catch (Throwable unexpected) { 2010 if (traceJNI) unexpected.printStackTrace(System.err); 2011 env.recordException(unexpected); 2012 return 0; 2013 } 2014 } 2015 2016 /** 2017 * CallNonvirtualFloatMethodV: invoke a virtual method that returns a float value 2018 * @param env A JREF index for the JNI environment object 2019 * @param objJREF a JREF index for the object instance 2020 * @param classJREF a JREF index for the class object that declares this method 2021 * @param methodID id of a MethodReference 2022 * @param argAddress a raw address to a variable argument list, each element is 2023 * 1-word or 2-words of the appropriate type for the method invocation 2024 * @return the float value returned from the method invocation 2025 */ 2026 private static float CallNonvirtualFloatMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 2027 Address argAddress) throws Exception { 2028 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualFloatMethodV \n"); 2029 RuntimeEntrypoints.checkJNICountDownToGC(); 2030 2031 try { 2032 Object obj = env.getJNIRef(objJREF); 2033 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Float, true); 2034 return Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value 2035 } catch (Throwable unexpected) { 2036 if (traceJNI) unexpected.printStackTrace(System.err); 2037 env.recordException(unexpected); 2038 return 0; 2039 } 2040 } 2041 2042 /** 2043 * CallNonvirtualFloatMethodA: invoke a virtual method that returns a float value 2044 * @param env A JREF index for the JNI environment object 2045 * @param objJREF a JREF index for the object instance 2046 * @param classJREF a JREF index for the class object that declares this method 2047 * @param methodID id of a MethodReference 2048 * @param argAddress a raw address to an array of unions in C, each element is 2-word 2049 * and hold an argument of the appropriate type for the method invocation 2050 * @return the float value returned from the method invocation 2051 */ 2052 private static float CallNonvirtualFloatMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 2053 Address argAddress) throws Exception { 2054 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualFloatMethodA \n"); 2055 RuntimeEntrypoints.checkJNICountDownToGC(); 2056 2057 try { 2058 Object obj = env.getJNIRef(objJREF); 2059 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Float, true); 2060 return Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value 2061 } catch (Throwable unexpected) { 2062 if (traceJNI) unexpected.printStackTrace(System.err); 2063 env.recordException(unexpected); 2064 return 0; 2065 } 2066 } 2067 2068 /** 2069 * CallNonvirtualDoubleMethod: invoke a virtual method that returns a double value 2070 * arguments passed using the vararg ... style 2071 * NOTE: the vararg's are not visible in the method signature here; 2072 * they are saved in the caller frame and the glue frame 2073 * @param env A JREF index for the JNI environment object 2074 * @param objJREF a JREF index for the object instance 2075 * @param classJREF a JREF index for the class object that declares this method 2076 * @param methodID id of a MethodReference 2077 * @return the double value returned from the method invocation 2078 */ 2079 private static double CallNonvirtualDoubleMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 2080 throws Exception { 2081 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualDoubleMethod \n"); 2082 RuntimeEntrypoints.checkJNICountDownToGC(); 2083 2084 try { 2085 Object obj = env.getJNIRef(objJREF); 2086 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Double, true); 2087 return Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value 2088 } catch (Throwable unexpected) { 2089 if (traceJNI) unexpected.printStackTrace(System.err); 2090 env.recordException(unexpected); 2091 return 0; 2092 } 2093 } 2094 2095 /** 2096 * CallNonvirtualDoubleMethodV: invoke a virtual method that returns a double value 2097 * @param env A JREF index for the JNI environment object 2098 * @param objJREF a JREF index for the object instance 2099 * @param classJREF a JREF index for the class object that declares this method 2100 * @param methodID id of a MethodReference 2101 * @param argAddress a raw address to a variable argument list, each element is 2102 * 1-word or 2-words of the appropriate type for the method invocation 2103 * @return the double value returned from the method invocation 2104 */ 2105 private static double CallNonvirtualDoubleMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 2106 Address argAddress) throws Exception { 2107 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualDoubleMethodV \n"); 2108 RuntimeEntrypoints.checkJNICountDownToGC(); 2109 2110 try { 2111 Object obj = env.getJNIRef(objJREF); 2112 Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Double, true); 2113 return Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value 2114 } catch (Throwable unexpected) { 2115 if (traceJNI) unexpected.printStackTrace(System.err); 2116 env.recordException(unexpected); 2117 return 0; 2118 } 2119 } 2120 2121 /** 2122 * CallNonvirtualDoubleMethodA: invoke a virtual method that returns a double value 2123 * @param env A JREF index for the JNI environment object 2124 * @param objJREF a JREF index for the object instance 2125 * @param classJREF a JREF index for the class object that declares this method 2126 * @param methodID id of a MethodReference 2127 * @param argAddress a raw address to an array of unions in C, each element is 2-word 2128 * and hold an argument of the appropriate type for the method invocation 2129 * @return the double value returned from the method invocation 2130 */ 2131 private static double CallNonvirtualDoubleMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 2132 Address argAddress) throws Exception { 2133 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualDoubleMethodA \n"); 2134 RuntimeEntrypoints.checkJNICountDownToGC(); 2135 2136 try { 2137 Object obj = env.getJNIRef(objJREF); 2138 Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Double, true); 2139 return Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value 2140 } catch (Throwable unexpected) { 2141 if (traceJNI) unexpected.printStackTrace(System.err); 2142 env.recordException(unexpected); 2143 return 0; 2144 } 2145 } 2146 2147 /** 2148 * CallNonvirtualVoidMethod: invoke a virtual method that returns a void value 2149 * arguments passed using the vararg ... style 2150 * NOTE: the vararg's are not visible in the method signature here; 2151 * they are saved in the caller frame and the glue frame 2152 * @param env A JREF index for the JNI environment object 2153 * @param objJREF a JREF index for the object instance 2154 * @param classJREF a JREF index for the class object that declares this method 2155 * @param methodID id of a MethodReference 2156 */ 2157 private static void CallNonvirtualVoidMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID) 2158 throws Exception { 2159 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualVoidMethod \n"); 2160 RuntimeEntrypoints.checkJNICountDownToGC(); 2161 2162 try { 2163 Object obj = env.getJNIRef(objJREF); 2164 JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Void, true); 2165 } catch (Throwable unexpected) { 2166 if (traceJNI) unexpected.printStackTrace(System.err); 2167 env.recordException(unexpected); 2168 } 2169 } 2170 2171 /** 2172 * CallNonvirtualVoidMethodV: invoke a virtual method that returns void 2173 * @param env A JREF index for the JNI environment object 2174 * @param objJREF a JREF index for the object instance 2175 * @param classJREF a JREF index for the class object that declares this method 2176 * @param methodID id of a MethodReference 2177 * @param argAddress a raw address to a variable argument list, each element is 2178 * 1-word or 2-words of the appropriate type for the method invocation 2179 */ 2180 private static void CallNonvirtualVoidMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID, 2181 Address argAddress) throws Exception { 2182 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualVoidMethodV \n"); 2183 RuntimeEntrypoints.checkJNICountDownToGC(); 2184 2185 try { 2186 Object obj = env.getJNIRef(objJREF); 2187 JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Void, true); 2188 } catch (Throwable unexpected) { 2189 if (traceJNI) unexpected.printStackTrace(System.err); 2190 env.recordException(unexpected); 2191 } 2192 } 2193 2194 /** 2195 * CallNonvirtualVoidMethodA: invoke a virtual method that returns void 2196 * @param env A JREF index for the JNI environment object 2197 * @param objJREF a JREF index for the object instance 2198 * @param classJREF a JREF index for the class object that declares this method 2199 * @param methodID id of a MethodReference 2200 * @param argAddress a raw address to an array of unions in C, each element is 2-word 2201 * and hold an argument of the appropriate type for the method invocation 2202 */ 2203 private static void CallNonvirtualVoidMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID, 2204 Address argAddress) throws Exception { 2205 if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualVoidMethodA \n"); 2206 RuntimeEntrypoints.checkJNICountDownToGC(); 2207 2208 try { 2209 Object obj = env.getJNIRef(objJREF); 2210 JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Void, true); 2211 } catch (Throwable unexpected) { 2212 if (traceJNI) unexpected.printStackTrace(System.err); 2213 env.recordException(unexpected); 2214 } 2215 } 2216 2217 /** 2218 * GetFieldID: return a field id, which can be cached in native code and reused 2219 * @param env A JREF index for the JNI environment object 2220 * @param classJREF a JREF index for the RVMClass object 2221 * @param fieldNameAddress a raw address to a null-terminated string in C for the field name 2222 * @param descriptorAddress a raw address to a null-terminated string in C for the descriptor 2223 * @return the fieldID of an instance field given the class, field name 2224 * and type. Return 0 if the field is not found 2225 * @exception NoSuchFieldError if the specified field cannot be found 2226 * @exception ExceptionInInitializerError if the class initializer fails 2227 * @exception OutOfMemoryError if the system runs out of memory 2228 */ 2229 private static int GetFieldID(JNIEnvironment env, int classJREF, Address fieldNameAddress, 2230 Address descriptorAddress) { 2231 if (traceJNI) VM.sysWrite("JNI called: GetFieldID \n"); 2232 RuntimeEntrypoints.checkJNICountDownToGC(); 2233 2234 try { 2235 if (traceJNI) 2236 VM.sysWriteln("called GetFieldID with classJREF = ",classJREF); 2237 Class<?> cls = (Class<?>) env.getJNIRef(classJREF); 2238 if (VM.VerifyAssertions) VM._assert(cls!=null); 2239 String fieldString = JNIHelpers.createStringFromC(fieldNameAddress); 2240 Atom fieldName = Atom.findOrCreateAsciiAtom(fieldString); 2241 2242 String descriptorString = JNIHelpers.createStringFromC(descriptorAddress); 2243 Atom descriptor = Atom.findOrCreateAsciiAtom(descriptorString); 2244 2245 // list of all instance fields including superclasses. 2246 // Iterate in reverse order since if there are multiple instance 2247 // fields of the same name & descriptor we want to find the most derived one. 2248 RVMField[] fields = java.lang.JikesRVMSupport.getTypeForClass(cls).getInstanceFields(); 2249 for (int i = fields.length-1; i>=0; i--) { 2250 RVMField f = fields[i]; 2251 if (f.getName() == fieldName && f.getDescriptor() == descriptor) { 2252 return f.getId(); 2253 } 2254 } 2255 2256 // create exception and return 0 if not found 2257 env.recordException(new NoSuchFieldError(fieldString + ", " + descriptorString + " of " + cls)); 2258 return 0; 2259 } catch (Throwable unexpected) { 2260 if (traceJNI) unexpected.printStackTrace(System.err); 2261 env.recordException(unexpected); 2262 return 0; 2263 } 2264 } 2265 2266 /** 2267 * GetObjectField: read a instance field of type Object 2268 * @param env A JREF index for the JNI environment object 2269 * @param objJREF a JREF index for the target object 2270 * @param fieldID the id for the RVMField that describes this field 2271 * @return the value of the Object field, converted to a JREF index 2272 * or 0 if the fieldID is incorrect 2273 */ 2274 private static int GetObjectField(JNIEnvironment env, int objJREF, int fieldID) { 2275 if (traceJNI) VM.sysWrite("JNI called: GetObjectField \n"); 2276 RuntimeEntrypoints.checkJNICountDownToGC(); 2277 2278 try { 2279 Object obj = env.getJNIRef(objJREF); 2280 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2281 Object objVal = field.getObjectUnchecked(obj); 2282 return env.pushJNIRef(objVal); 2283 } catch (Throwable unexpected) { 2284 if (traceJNI) unexpected.printStackTrace(System.err); 2285 env.recordException(unexpected); 2286 return 0; 2287 } 2288 } 2289 2290 /** 2291 * GetBooleanField: read an instance field of type boolean 2292 * @param env A JREF index for the JNI environment object 2293 * @param objJREF a JREF index for the target object 2294 * @param fieldID the id for the RVMField that describes this field 2295 * @return the value of the boolean field, or 0 if the fieldID is incorrect 2296 */ 2297 private static int GetBooleanField(JNIEnvironment env, int objJREF, int fieldID) { 2298 if (traceJNI) VM.sysWrite("JNI called: GetBooleanField \n"); 2299 RuntimeEntrypoints.checkJNICountDownToGC(); 2300 2301 try { 2302 Object obj = env.getJNIRef(objJREF); 2303 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2304 return field.getBooleanValueUnchecked(obj) ? 1 : 0; 2305 } catch (Throwable unexpected) { 2306 if (traceJNI) unexpected.printStackTrace(System.err); 2307 env.recordException(unexpected); 2308 return 0; 2309 } 2310 } 2311 2312 /** 2313 * GetByteField: read an instance field of type byte 2314 * @param env A JREF index for the JNI environment object 2315 * @param objJREF a JREF index for the target object 2316 * @param fieldID the id for the RVMField that describes this field 2317 * @return the value of the byte field, or 0 if the fieldID is incorrect 2318 */ 2319 private static int GetByteField(JNIEnvironment env, int objJREF, int fieldID) { 2320 if (traceJNI) VM.sysWrite("JNI called: GetByteField \n"); 2321 RuntimeEntrypoints.checkJNICountDownToGC(); 2322 2323 try { 2324 Object obj = env.getJNIRef(objJREF); 2325 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2326 return field.getByteValueUnchecked(obj); 2327 } catch (Throwable unexpected) { 2328 if (traceJNI) unexpected.printStackTrace(System.err); 2329 env.recordException(unexpected); 2330 return 0; 2331 } 2332 } 2333 2334 /** 2335 * GetCharField: read an instance field of type character 2336 * @param env A JREF index for the JNI environment object 2337 * @param objJREF a JREF index for the target object 2338 * @param fieldID the id for the RVMField that describes this field 2339 * @return the value of the character field, or 0 if the fieldID is incorrect 2340 */ 2341 private static int GetCharField(JNIEnvironment env, int objJREF, int fieldID) { 2342 if (traceJNI) VM.sysWrite("JNI called: GetCharField \n"); 2343 RuntimeEntrypoints.checkJNICountDownToGC(); 2344 2345 try { 2346 Object obj = env.getJNIRef(objJREF); 2347 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2348 return field.getCharValueUnchecked(obj); 2349 } catch (Throwable unexpected) { 2350 if (traceJNI) unexpected.printStackTrace(System.err); 2351 env.recordException(unexpected); 2352 return 0; 2353 } 2354 } 2355 2356 /** 2357 * GetShortField: read an instance field of type short 2358 * @param env A JREF index for the JNI environment object 2359 * @param objJREF a JREF index for the target object 2360 * @param fieldID the id for the RVMField that describes this field 2361 * @return the value of the short field, or 0 if the fieldID is incorrect 2362 */ 2363 private static int GetShortField(JNIEnvironment env, int objJREF, int fieldID) { 2364 if (traceJNI) VM.sysWrite("JNI called: GetShortField \n"); 2365 RuntimeEntrypoints.checkJNICountDownToGC(); 2366 2367 try { 2368 Object obj = env.getJNIRef(objJREF); 2369 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2370 return field.getShortValueUnchecked(obj); 2371 } catch (Throwable unexpected) { 2372 if (traceJNI) unexpected.printStackTrace(System.err); 2373 env.recordException(unexpected); 2374 return 0; 2375 } 2376 } 2377 2378 /** 2379 * GetIntField: read an instance field of type integer 2380 * @param env A JREF index for the JNI environment object 2381 * @param objJREF a JREF index for the target object 2382 * @param fieldID the id for the RVMField that describes this field 2383 * @return the value of the integer field, or 0 if the fieldID is incorrect 2384 */ 2385 private static int GetIntField(JNIEnvironment env, int objJREF, int fieldID) { 2386 if (traceJNI) VM.sysWrite("JNI called: GetIntField \n"); 2387 RuntimeEntrypoints.checkJNICountDownToGC(); 2388 2389 try { 2390 Object obj = env.getJNIRef(objJREF); 2391 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2392 return field.getIntValueUnchecked(obj); 2393 } catch (Throwable unexpected) { 2394 if (traceJNI) unexpected.printStackTrace(System.err); 2395 env.recordException(unexpected); 2396 return 0; 2397 } 2398 } 2399 2400 /** 2401 * GetLongField: read an instance field of type long 2402 * @param env A JREF index for the JNI environment object 2403 * @param objJREF a JREF index for the target object 2404 * @param fieldID the id for the RVMField that describes this field 2405 * @return the value of the long field or 0 if the fieldID is incorrect 2406 */ 2407 private static long GetLongField(JNIEnvironment env, int objJREF, int fieldID) { 2408 if (traceJNI) VM.sysWrite("JNI called: GetLongField \n"); 2409 RuntimeEntrypoints.checkJNICountDownToGC(); 2410 2411 try { 2412 Object obj = env.getJNIRef(objJREF); 2413 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2414 return field.getLongValueUnchecked(obj); 2415 } catch (Throwable unexpected) { 2416 if (traceJNI) unexpected.printStackTrace(System.err); 2417 env.recordException(unexpected); 2418 return 0L; 2419 } 2420 } 2421 2422 /** 2423 * GetFloatField: read an instance field of type float 2424 * @param env A JREF index for the JNI environment object 2425 * @param objJREF a JREF index for the target object 2426 * @param fieldID the id for the RVMField that describes this field 2427 * @return the value of the float field or 0 if the fieldID is incorrect 2428 */ 2429 private static float GetFloatField(JNIEnvironment env, int objJREF, int fieldID) { 2430 if (traceJNI) VM.sysWrite("JNI called: GetFloatField \n"); 2431 RuntimeEntrypoints.checkJNICountDownToGC(); 2432 2433 try { 2434 Object obj = env.getJNIRef(objJREF); 2435 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2436 return field.getFloatValueUnchecked(obj); 2437 } catch (Throwable unexpected) { 2438 if (traceJNI) unexpected.printStackTrace(System.err); 2439 env.recordException(unexpected); 2440 return 0f; 2441 } 2442 } 2443 2444 /** 2445 * GetDoubleField: read an instance field of type double 2446 * @param env A JREF index for the JNI environment object 2447 * @param objJREF a JREF index for the target object 2448 * @param fieldID the id for the RVMField that describes this field 2449 * @return the value of the double field or 0 if the fieldID is incorrect 2450 */ 2451 private static double GetDoubleField(JNIEnvironment env, int objJREF, int fieldID) { 2452 if (traceJNI) VM.sysWrite("JNI called: GetDoubleField \n"); 2453 RuntimeEntrypoints.checkJNICountDownToGC(); 2454 2455 try { 2456 Object obj = env.getJNIRef(objJREF); 2457 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2458 return field.getDoubleValueUnchecked(obj); 2459 } catch (Throwable unexpected) { 2460 if (traceJNI) unexpected.printStackTrace(System.err); 2461 env.recordException(unexpected); 2462 return 0.0; 2463 } 2464 } 2465 2466 /** 2467 * SetObjectField: set a instance field of type Object 2468 * @param env A JREF index for the JNI environment object 2469 * @param objJREF a JREF index for the target object 2470 * @param fieldID the id for the RVMField that describes this field 2471 * @param valueJREF a JREF index for the value to assign 2472 */ 2473 private static void SetObjectField(JNIEnvironment env, int objJREF, int fieldID, int valueJREF) { 2474 if (traceJNI) VM.sysWrite("JNI called: SetObjectField \n"); 2475 RuntimeEntrypoints.checkJNICountDownToGC(); 2476 2477 try { 2478 Object obj = env.getJNIRef(objJREF); 2479 Object value = env.getJNIRef(valueJREF); 2480 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2481 field.setObjectValueUnchecked(obj, value); 2482 } catch (Throwable unexpected) { 2483 if (traceJNI) unexpected.printStackTrace(System.err); 2484 env.recordException(unexpected); 2485 } 2486 } 2487 2488 /** 2489 * SetBooleanField: set an instance field of type boolean 2490 * @param env A JREF index for the JNI environment object 2491 * @param objJREF a JREF index for the target object 2492 * @param fieldID the id for the RVMField that describes this field 2493 * @param value boolean value to assign 2494 */ 2495 private static void SetBooleanField(JNIEnvironment env, int objJREF, int fieldID, boolean value) { 2496 if (traceJNI) VM.sysWrite("JNI called: SetBooleanField \n"); 2497 RuntimeEntrypoints.checkJNICountDownToGC(); 2498 2499 try { 2500 Object obj = env.getJNIRef(objJREF); 2501 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2502 field.setBooleanValueUnchecked(obj, value); 2503 } catch (Throwable unexpected) { 2504 if (traceJNI) unexpected.printStackTrace(System.err); 2505 env.recordException(unexpected); 2506 } 2507 } 2508 2509 /** 2510 * SetByteField: set an instance field of type byte 2511 * @param env A JREF index for the JNI environment object 2512 * @param objJREF a JREF index for the target object 2513 * @param fieldID the id for the RVMField that describes this field 2514 * @param value byte value to assign 2515 */ 2516 private static void SetByteField(JNIEnvironment env, int objJREF, int fieldID, byte value) { 2517 if (traceJNI) VM.sysWrite("JNI called: SetByteField \n"); 2518 RuntimeEntrypoints.checkJNICountDownToGC(); 2519 2520 try { 2521 Object obj = env.getJNIRef(objJREF); 2522 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2523 field.setByteValueUnchecked(obj, value); 2524 } catch (Throwable unexpected) { 2525 if (traceJNI) unexpected.printStackTrace(System.err); 2526 env.recordException(unexpected); 2527 } 2528 } 2529 2530 /** 2531 * SetCharField: set an instance field of type char 2532 * @param env A JREF index for the JNI environment object 2533 * @param objJREF a JREF index for the target object 2534 * @param fieldID the id for the RVMField that describes this field 2535 * @param value char value to assign 2536 */ 2537 private static void SetCharField(JNIEnvironment env, int objJREF, int fieldID, char value) { 2538 if (traceJNI) VM.sysWrite("JNI called: SetCharField \n"); 2539 RuntimeEntrypoints.checkJNICountDownToGC(); 2540 2541 try { 2542 Object obj = env.getJNIRef(objJREF); 2543 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2544 field.setCharValueUnchecked(obj, value); 2545 } catch (Throwable unexpected) { 2546 if (traceJNI) unexpected.printStackTrace(System.err); 2547 env.recordException(unexpected); 2548 } 2549 } 2550 2551 /** 2552 * SetShortField: set an instance field of type short 2553 * @param env A JREF index for the JNI environment object 2554 * @param objJREF a JREF index for the target object 2555 * @param fieldID the id for the RVMField that describes this field 2556 * @param value short value to assign 2557 */ 2558 private static void SetShortField(JNIEnvironment env, int objJREF, int fieldID, short value) { 2559 if (traceJNI) VM.sysWrite("JNI called: SetShortField \n"); 2560 RuntimeEntrypoints.checkJNICountDownToGC(); 2561 2562 try { 2563 Object obj = env.getJNIRef(objJREF); 2564 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2565 field.setShortValueUnchecked(obj, value); 2566 } catch (Throwable unexpected) { 2567 if (traceJNI) unexpected.printStackTrace(System.err); 2568 env.recordException(unexpected); 2569 } 2570 } 2571 2572 /** 2573 * SetIntField: set an instance field of type integer 2574 * @param env A JREF index for the JNI environment object 2575 * @param objJREF a JREF index for the target object 2576 * @param fieldID the id for the RVMField that describes this field 2577 * @param value integer value to assign 2578 */ 2579 private static void SetIntField(JNIEnvironment env, int objJREF, int fieldID, int value) { 2580 if (traceJNI) VM.sysWrite("JNI called: SetIntField \n"); 2581 RuntimeEntrypoints.checkJNICountDownToGC(); 2582 2583 try { 2584 Object obj = env.getJNIRef(objJREF); 2585 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2586 field.setIntValueUnchecked(obj, value); 2587 } catch (Throwable unexpected) { 2588 if (traceJNI) unexpected.printStackTrace(System.err); 2589 env.recordException(unexpected); 2590 } 2591 } 2592 2593 /** 2594 * SetLongField: set an instance field of type long 2595 * @param env A JREF index for the JNI environment object 2596 * @param objJREF a JREF index for the target object 2597 * @param fieldID the id for the RVMField that describes this field 2598 * @param value long value to assign 2599 */ 2600 private static void SetLongField(JNIEnvironment env, int objJREF, int fieldID, long value) { 2601 if (traceJNI) VM.sysWrite("JNI called: SetLongField \n"); 2602 RuntimeEntrypoints.checkJNICountDownToGC(); 2603 2604 try { 2605 Object obj = env.getJNIRef(objJREF); 2606 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2607 field.setLongValueUnchecked(obj, value); 2608 } catch (Throwable unexpected) { 2609 if (traceJNI) unexpected.printStackTrace(System.err); 2610 env.recordException(unexpected); 2611 } 2612 } 2613 2614 /** 2615 * SetFloatField: set an instance field of type float 2616 * @param env A JREF index for the JNI environment object 2617 * @param objJREF a JREF index for the target object 2618 * @param fieldID the id for the RVMField that describes this field 2619 * @param value float value to assign 2620 */ 2621 private static void SetFloatField(JNIEnvironment env, int objJREF, int fieldID, float value) { 2622 if (traceJNI) VM.sysWrite("JNI called: SetFloatField \n"); 2623 RuntimeEntrypoints.checkJNICountDownToGC(); 2624 2625 try { 2626 Object obj = env.getJNIRef(objJREF); 2627 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2628 field.setFloatValueUnchecked(obj, value); 2629 } catch (Throwable unexpected) { 2630 if (traceJNI) unexpected.printStackTrace(System.err); 2631 env.recordException(unexpected); 2632 } 2633 } 2634 2635 /** 2636 * SetDoubleField: set an instance field of type double 2637 * @param env A JREF index for the JNI environment object 2638 * @param objJREF a JREF index for the target object 2639 * @param fieldID the id for the RVMField that describes this field 2640 * @param value double value to assign 2641 */ 2642 private static void SetDoubleField(JNIEnvironment env, int objJREF, int fieldID, double value) { 2643 if (traceJNI) VM.sysWrite("JNI called: SetDoubleField \n"); 2644 RuntimeEntrypoints.checkJNICountDownToGC(); 2645 2646 try { 2647 Object obj = env.getJNIRef(objJREF); 2648 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 2649 field.setDoubleValueUnchecked(obj, value); 2650 } catch (Throwable unexpected) { 2651 if (traceJNI) unexpected.printStackTrace(System.err); 2652 env.recordException(unexpected); 2653 } 2654 } 2655 2656 /** 2657 * GetStaticMethodID: return the method ID for invocation later 2658 * @param env A JREF index for the JNI environment object 2659 * @param classJREF a JREF index for the class object 2660 * @param methodNameAddress a raw address to a null-terminated string in C for the method name 2661 * @param methodSigAddress a raw address to a null-terminated string in C for <DOCUMENTME TODO> 2662 * @return a method ID or null if it fails 2663 * @exception NoSuchMethodError if the method is not found 2664 * @exception ExceptionInInitializerError if the initializer fails 2665 * @exception OutOfMemoryError if the system runs out of memory 2666 */ 2667 private static int GetStaticMethodID(JNIEnvironment env, int classJREF, Address methodNameAddress, 2668 Address methodSigAddress) { 2669 if (traceJNI) VM.sysWrite("JNI called: GetStaticMethodID \n"); 2670 RuntimeEntrypoints.checkJNICountDownToGC(); 2671 2672 try { 2673 // obtain the names as String from the native space 2674 String methodString = JNIHelpers.createStringFromC(methodNameAddress); 2675 Atom methodName = Atom.findOrCreateAsciiAtom(methodString); 2676 String sigString = JNIHelpers.createStringFromC(methodSigAddress); 2677 Atom sigName = Atom.findOrCreateAsciiAtom(sigString); 2678 2679 // get the target class 2680 Class<?> jcls = (Class<?>) env.getJNIRef(classJREF); 2681 RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls); 2682 if (!type.isClassType()) { 2683 env.recordException(new NoSuchMethodError()); 2684 return 0; 2685 } 2686 2687 RVMClass klass = type.asClass(); 2688 if (!klass.isInitialized()) { 2689 RuntimeEntrypoints.initializeClassForDynamicLink(klass); 2690 } 2691 2692 // Find the target method 2693 RVMMethod meth = klass.findStaticMethod(methodName, sigName); 2694 if (meth == null) { 2695 env.recordException(new NoSuchMethodError()); 2696 return 0; 2697 } 2698 2699 if (traceJNI) VM.sysWrite("got method " + meth + "\n"); 2700 return meth.getId(); 2701 } catch (Throwable unexpected) { 2702 if (traceJNI) unexpected.printStackTrace(System.err); 2703 env.recordException(unexpected); 2704 return 0; 2705 } 2706 } 2707 2708 /** 2709 * CallStaticObjectMethod: invoke a static method that returns an object value 2710 * arguments passed using the vararg ... style 2711 * NOTE: the vararg's are not visible in the method signature here; they are saved 2712 * in the caller frame and the glue frame 2713 * @param env A JREF index for the JNI environment object 2714 * @param classJREF a JREF index for the class object 2715 * @param methodID id of a MethodReference 2716 * @return the JREF index for the object returned from the method invocation 2717 */ 2718 private static int CallStaticObjectMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 2719 if (traceJNI) VM.sysWrite("JNI called: CallStaticObjectMethod \n"); 2720 RuntimeEntrypoints.checkJNICountDownToGC(); 2721 2722 try { 2723 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, null); 2724 return env.pushJNIRef(returnObj); 2725 } catch (Throwable unexpected) { 2726 if (traceJNI) unexpected.printStackTrace(System.err); 2727 env.recordException(unexpected); 2728 return 0; 2729 } 2730 } 2731 2732 /** 2733 * CallStaticObjectMethodV: invoke a static method that returns an object 2734 * @param env A JREF index for the JNI environment object 2735 * @param classJREF a JREF index for the class object 2736 * @param methodID id of a MethodReference 2737 * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words 2738 * of the appropriate type for the method invocation 2739 * @return the JREF index for the object returned from the method invocation 2740 */ 2741 private static int CallStaticObjectMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 2742 throws Exception { 2743 if (traceJNI) VM.sysWrite("JNI called: CallStaticObjectMethodV \n"); 2744 RuntimeEntrypoints.checkJNICountDownToGC(); 2745 2746 try { 2747 Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, null); 2748 return env.pushJNIRef(returnObj); 2749 } catch (Throwable unexpected) { 2750 if (traceJNI) unexpected.printStackTrace(System.err); 2751 env.recordException(unexpected); 2752 return 0; 2753 } 2754 } 2755 2756 /** 2757 * CallStaticObjectMethodA: invoke a static method that returns an object 2758 * @param env A JREF index for the JNI environment object 2759 * @param classJREF a JREF index for the class object 2760 * @param methodID id of a MethodReference 2761 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 2762 * of the appropriate type for the method invocation 2763 * @return the JREF index for the object returned from the method invocation 2764 */ 2765 private static int CallStaticObjectMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 2766 throws Exception { 2767 if (traceJNI) VM.sysWrite("JNI called: CallStaticObjectMethodA \n"); 2768 RuntimeEntrypoints.checkJNICountDownToGC(); 2769 2770 try { 2771 Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, null); 2772 return env.pushJNIRef(returnObj); 2773 } catch (Throwable unexpected) { 2774 if (traceJNI) unexpected.printStackTrace(System.err); 2775 env.recordException(unexpected); 2776 return 0; 2777 } 2778 } 2779 2780 /** 2781 * CallStaticBooleanMethod: invoke a static method that returns a boolean value 2782 * arguments passed using the vararg ... style 2783 * NOTE: the vararg's are not visible in the method signature here; they are saved 2784 * in the caller frame and the glue frame 2785 * @param env A JREF index for the JNI environment object 2786 * @param classJREF a JREF index for the class object 2787 * @param methodID id of a MethodReference 2788 * @return the boolean value returned from the method invocation 2789 */ 2790 private static boolean CallStaticBooleanMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 2791 if (traceJNI) VM.sysWrite("JNI called: CallStaticBooleanMethod \n"); 2792 RuntimeEntrypoints.checkJNICountDownToGC(); 2793 2794 try { 2795 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Boolean); 2796 return Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value 2797 } catch (Throwable unexpected) { 2798 if (traceJNI) unexpected.printStackTrace(System.err); 2799 env.recordException(unexpected); 2800 return false; 2801 } 2802 } 2803 2804 /** 2805 * CallStaticBooleanMethodV: invoke a static method that returns a boolean value 2806 * @param env A JREF index for the JNI environment object 2807 * @param classJREF a JREF index for the class object 2808 * @param methodID id of a MethodReference 2809 * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words 2810 * of the appropriate type for the method invocation 2811 * @return the boolean value returned from the method invocation 2812 */ 2813 private static boolean CallStaticBooleanMethodV(JNIEnvironment env, int classJREF, int methodID, 2814 Address argAddress) throws Exception { 2815 if (traceJNI) VM.sysWrite("JNI called: CallStaticBooleanMethodV \n"); 2816 RuntimeEntrypoints.checkJNICountDownToGC(); 2817 2818 try { 2819 Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Boolean); 2820 return Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value 2821 } catch (Throwable unexpected) { 2822 if (traceJNI) unexpected.printStackTrace(System.err); 2823 env.recordException(unexpected); 2824 return false; 2825 } 2826 } 2827 2828 /** 2829 * CallStaticBooleanMethodA: invoke a static method that returns a boolean value 2830 * @param env A JREF index for the JNI environment object 2831 * @param classJREF a JREF index for the class object 2832 * @param methodID id of a MethodReference 2833 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 2834 * of the appropriate type for the method invocation 2835 * @return the boolean value returned from the method invocation 2836 */ 2837 private static boolean CallStaticBooleanMethodA(JNIEnvironment env, int classJREF, int methodID, 2838 Address argAddress) throws Exception { 2839 if (traceJNI) VM.sysWrite("JNI called: CallStaticBooleanMethodA \n"); 2840 RuntimeEntrypoints.checkJNICountDownToGC(); 2841 2842 try { 2843 Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Boolean); 2844 return Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value 2845 } catch (Throwable unexpected) { 2846 if (traceJNI) unexpected.printStackTrace(System.err); 2847 env.recordException(unexpected); 2848 return false; 2849 } 2850 } 2851 2852 /** 2853 * CallStaticByteMethod: invoke a static method that returns a byte value 2854 * arguments passed using the vararg ... style 2855 * NOTE: the vararg's are not visible in the method signature here; they are saved 2856 * in the caller frame and the glue frame 2857 * @param env A JREF index for the JNI environment object 2858 * @param classJREF a JREF index for the class object 2859 * @param methodID id of a MethodReference 2860 * @return the byte value returned from the method invocation 2861 */ 2862 private static byte CallStaticByteMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 2863 if (traceJNI) VM.sysWrite("JNI called: CallStaticByteMethod \n"); 2864 RuntimeEntrypoints.checkJNICountDownToGC(); 2865 2866 try { 2867 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Byte); 2868 return Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value 2869 } catch (Throwable unexpected) { 2870 if (traceJNI) unexpected.printStackTrace(System.err); 2871 env.recordException(unexpected); 2872 return 0; 2873 } 2874 } 2875 2876 /** 2877 * CallStaticByteMethodV: invoke a static method that returns a byte value 2878 * @param env A JREF index for the JNI environment object 2879 * @param classJREF a JREF index for the class object 2880 * @param methodID id of a MethodReference 2881 * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words 2882 * of the appropriate type for the method invocation 2883 * @return the byte value returned from the method invocation 2884 */ 2885 private static byte CallStaticByteMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 2886 throws Exception { 2887 if (traceJNI) VM.sysWrite("JNI called: CallStaticByteMethodV \n"); 2888 RuntimeEntrypoints.checkJNICountDownToGC(); 2889 2890 try { 2891 Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Byte); 2892 return Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value 2893 } catch (Throwable unexpected) { 2894 if (traceJNI) unexpected.printStackTrace(System.err); 2895 env.recordException(unexpected); 2896 return 0; 2897 } 2898 } 2899 2900 /** 2901 * CallStaticByteMethodA: invoke a static method that returns a byte value 2902 * @param env A JREF index for the JNI environment object 2903 * @param classJREF a JREF index for the class object 2904 * @param methodID id of a MethodReference 2905 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 2906 * of the appropriate type for the method invocation 2907 * @return the byte value returned from the method invocation 2908 */ 2909 private static byte CallStaticByteMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 2910 throws Exception { 2911 if (traceJNI) VM.sysWrite("JNI called: CallStaticByteMethodA \n"); 2912 RuntimeEntrypoints.checkJNICountDownToGC(); 2913 2914 try { 2915 Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Byte); 2916 return Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value 2917 } catch (Throwable unexpected) { 2918 if (traceJNI) unexpected.printStackTrace(System.err); 2919 env.recordException(unexpected); 2920 return 0; 2921 } 2922 } 2923 2924 /** 2925 * CallStaticCharMethod: invoke a static method that returns a char value 2926 * arguments passed using the vararg ... style 2927 * NOTE: the vararg's are not visible in the method signature here; they are saved 2928 * in the caller frame and the glue frame 2929 * @param env A JREF index for the JNI environment object 2930 * @param classJREF a JREF index for the class object 2931 * @param methodID id of a MethodReference 2932 * @return the char value returned from the method invocation 2933 */ 2934 private static char CallStaticCharMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 2935 if (traceJNI) VM.sysWrite("JNI called: CallStaticCharMethod \n"); 2936 RuntimeEntrypoints.checkJNICountDownToGC(); 2937 2938 try { 2939 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Char); 2940 return Reflection.unwrapChar(returnObj); // should be a wrapper for a char value 2941 } catch (Throwable unexpected) { 2942 if (traceJNI) unexpected.printStackTrace(System.err); 2943 env.recordException(unexpected); 2944 return 0; 2945 } 2946 } 2947 2948 /** 2949 * CallStaticCharMethodV: invoke a static method that returns a char value 2950 * @param env A JREF index for the JNI environment object 2951 * @param classJREF a JREF index for the class object 2952 * @param methodID id of a MethodReference 2953 * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words 2954 * of the appropriate type for the method invocation 2955 * @return the char value returned from the method invocation 2956 */ 2957 private static char CallStaticCharMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 2958 throws Exception { 2959 if (traceJNI) VM.sysWrite("JNI called: CallStaticCharMethodV \n"); 2960 RuntimeEntrypoints.checkJNICountDownToGC(); 2961 2962 try { 2963 Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Char); 2964 return Reflection.unwrapChar(returnObj); // should be a wrapper for a char value 2965 } catch (Throwable unexpected) { 2966 if (traceJNI) unexpected.printStackTrace(System.err); 2967 env.recordException(unexpected); 2968 return 0; 2969 } 2970 } 2971 2972 /** 2973 * CallStaticCharMethodA: invoke a static method that returns a char value 2974 * @param env A JREF index for the JNI environment object 2975 * @param classJREF a JREF index for the class object 2976 * @param methodID id of a MethodReference 2977 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 2978 * of the appropriate type for the method invocation 2979 * @return the char value returned from the method invocation 2980 */ 2981 private static char CallStaticCharMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 2982 throws Exception { 2983 if (traceJNI) VM.sysWrite("JNI called: CallStaticCharMethodA \n"); 2984 RuntimeEntrypoints.checkJNICountDownToGC(); 2985 2986 try { 2987 Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Char); 2988 return Reflection.unwrapChar(returnObj); // should be a wrapper for a char value 2989 } catch (Throwable unexpected) { 2990 if (traceJNI) unexpected.printStackTrace(System.err); 2991 env.recordException(unexpected); 2992 return 0; 2993 } 2994 } 2995 2996 /** 2997 * CallStaticShortMethod: invoke a static method that returns a short value 2998 * arguments passed using the vararg ... style 2999 * NOTE: the vararg's are not visible in the method signature here; they are saved 3000 * in the caller frame and the glue frame 3001 * @param env A JREF index for the JNI environment object 3002 * @param classJREF a JREF index for the class object 3003 * @param methodID id of a MethodReference 3004 * @return the short value returned from the method invocation 3005 */ 3006 private static short CallStaticShortMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 3007 if (traceJNI) VM.sysWrite("JNI called: CallStaticShortMethod \n"); 3008 RuntimeEntrypoints.checkJNICountDownToGC(); 3009 3010 try { 3011 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Short); 3012 return Reflection.unwrapShort(returnObj); // should be a wrapper for an short value 3013 } catch (Throwable unexpected) { 3014 if (traceJNI) unexpected.printStackTrace(System.err); 3015 env.recordException(unexpected); 3016 return 0; 3017 } 3018 } 3019 3020 /** 3021 * CallStaticShortMethodV: invoke a static method that returns a short value 3022 * @param env A JREF index for the JNI environment object 3023 * @param classJREF a JREF index for the class object 3024 * @param methodID id of a MethodReference 3025 * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words 3026 * of the appropriate type for the method invocation 3027 * @return the short value returned from the method invocation 3028 */ 3029 private static short CallStaticShortMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3030 throws Exception { 3031 if (traceJNI) VM.sysWrite("JNI called: CallStaticShortMethodV \n"); 3032 RuntimeEntrypoints.checkJNICountDownToGC(); 3033 3034 try { 3035 Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Short); 3036 return Reflection.unwrapShort(returnObj); // should be a wrapper for a short value 3037 } catch (Throwable unexpected) { 3038 if (traceJNI) unexpected.printStackTrace(System.err); 3039 env.recordException(unexpected); 3040 return 0; 3041 } 3042 } 3043 3044 /** 3045 * CallStaticShortMethodA: invoke a static method that returns a short value 3046 * @param env A JREF index for the JNI environment object 3047 * @param classJREF a JREF index for the class object 3048 * @param methodID id of a MethodReference 3049 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 3050 * of the appropriate type for the method invocation 3051 * @return the short value returned from the method invocation 3052 */ 3053 private static short CallStaticShortMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3054 throws Exception { 3055 if (traceJNI) VM.sysWrite("JNI called: CallStaticShortMethodA \n"); 3056 RuntimeEntrypoints.checkJNICountDownToGC(); 3057 3058 try { 3059 Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Short); 3060 return Reflection.unwrapShort(returnObj); // should be a wrapper for a short value 3061 } catch (Throwable unexpected) { 3062 if (traceJNI) unexpected.printStackTrace(System.err); 3063 env.recordException(unexpected); 3064 return 0; 3065 } 3066 } 3067 3068 /** 3069 * CallStaticIntMethod: invoke a static method that returns an integer value 3070 * arguments passed using the vararg ... style 3071 * NOTE: the vararg's are not visible in the method signature here; they are saved 3072 * in the caller frame and the glue frame 3073 * @param env A JREF index for the JNI environment object 3074 * @param classJREF a JREF index for the class object 3075 * @param methodID id of a MethodReference 3076 * @return the integer value returned from the method invocation 3077 */ 3078 private static int CallStaticIntMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 3079 if (traceJNI) VM.sysWrite("JNI called: CallStaticIntMethod \n"); 3080 RuntimeEntrypoints.checkJNICountDownToGC(); 3081 3082 try { 3083 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Int); 3084 return Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value 3085 } catch (Throwable unexpected) { 3086 if (traceJNI) unexpected.printStackTrace(System.err); 3087 env.recordException(unexpected); 3088 return 0; 3089 } 3090 } 3091 3092 /** 3093 * CallStaticIntMethodV: invoke a static method that returns an integer value 3094 * @param env A JREF index for the JNI environment object 3095 * @param classJREF a JREF index for the class object 3096 * @param methodID id of a MethodReference 3097 * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words 3098 * of the appropriate type for the method invocation 3099 * @return the integer value returned from the method invocation 3100 */ 3101 private static int CallStaticIntMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3102 throws Exception { 3103 if (traceJNI) VM.sysWrite("JNI called: CallStaticIntMethodV \n"); 3104 RuntimeEntrypoints.checkJNICountDownToGC(); 3105 3106 try { 3107 Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Int); 3108 return Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value 3109 } catch (Throwable unexpected) { 3110 if (traceJNI) unexpected.printStackTrace(System.err); 3111 env.recordException(unexpected); 3112 return 0; 3113 } 3114 } 3115 3116 /** 3117 * CallStaticIntMethodA: invoke a static method that returns an integer value 3118 * @param env A JREF index for the JNI environment object 3119 * @param classJREF a JREF index for the class object 3120 * @param methodID id of a MethodReference 3121 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 3122 * of the appropriate type for the method invocation 3123 * @return the integer value returned from the method invocation 3124 */ 3125 private static int CallStaticIntMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3126 throws Exception { 3127 if (traceJNI) VM.sysWrite("JNI called: CallStaticIntMethodA \n"); 3128 RuntimeEntrypoints.checkJNICountDownToGC(); 3129 3130 try { 3131 Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Int); 3132 return Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value 3133 } catch (Throwable unexpected) { 3134 if (traceJNI) unexpected.printStackTrace(System.err); 3135 env.recordException(unexpected); 3136 return 0; 3137 } 3138 } 3139 3140 /** 3141 * CallStaticLongMethod: invoke a static method that returns a long value 3142 * arguments passed using the vararg ... style 3143 * NOTE: the vararg's are not visible in the method signature here; they are saved 3144 * in the caller frame and the glue frame 3145 * @param env A JREF index for the JNI environment object 3146 * @param classJREF a JREF index for the class object 3147 * @param methodID id of a MethodReference 3148 * @return the long value returned from the method invocation 3149 */ 3150 private static long CallStaticLongMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 3151 if (traceJNI) VM.sysWrite("JNI called: CallStaticLongMethod \n"); 3152 RuntimeEntrypoints.checkJNICountDownToGC(); 3153 3154 try { 3155 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Long); 3156 return Reflection.unwrapLong(returnObj); // should be a wrapper for a long value 3157 } catch (Throwable unexpected) { 3158 if (traceJNI) unexpected.printStackTrace(System.err); 3159 env.recordException(unexpected); 3160 return 0L; 3161 } 3162 } 3163 3164 /** 3165 * CallStaticLongMethodV: invoke a static method that returns a long value 3166 * @param env A JREF index for the JNI environment object 3167 * @param classJREF a JREF index for the class object 3168 * @param methodID id of a MethodReference 3169 * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words 3170 * of the appropriate type for the method invocation 3171 * @return the long value returned from the method invocation 3172 */ 3173 private static long CallStaticLongMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3174 throws Exception { 3175 if (traceJNI) VM.sysWrite("JNI called: CallStaticLongMethodV \n"); 3176 RuntimeEntrypoints.checkJNICountDownToGC(); 3177 3178 try { 3179 Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Long); 3180 return Reflection.unwrapLong(returnObj); // should be a wrapper for a long value 3181 } catch (Throwable unexpected) { 3182 if (traceJNI) unexpected.printStackTrace(System.err); 3183 env.recordException(unexpected); 3184 return 0L; 3185 } 3186 } 3187 3188 /** 3189 * CallStaticLongMethodA: invoke a static method that returns a long value 3190 * @param env A JREF index for the JNI environment object 3191 * @param classJREF a JREF index for the class object 3192 * @param methodID id of a MethodReference 3193 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 3194 * of the appropriate type for the method invocation 3195 * @return the long value returned from the method invocation 3196 */ 3197 private static long CallStaticLongMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3198 throws Exception { 3199 if (traceJNI) VM.sysWrite("JNI called: CallStaticLongMethodA \n"); 3200 RuntimeEntrypoints.checkJNICountDownToGC(); 3201 3202 try { 3203 Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Long); 3204 return Reflection.unwrapLong(returnObj); // should be a wrapper for a long value 3205 } catch (Throwable unexpected) { 3206 if (traceJNI) unexpected.printStackTrace(System.err); 3207 env.recordException(unexpected); 3208 return 0L; 3209 } 3210 } 3211 3212 /** 3213 * CallStaticFloagMethod: invoke a static method that returns a float value 3214 * arguments passed using the vararg ... style 3215 * NOTE: the vararg's are not visible in the method signature here; they are saved 3216 * in the caller frame and the glue frame 3217 * @param env A JREF index for the JNI environment object 3218 * @param classJREF a JREF index for the class object 3219 * @param methodID id of a MethodReference 3220 * @return the float value returned from the method invocation 3221 */ 3222 private static float CallStaticFloatMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 3223 if (traceJNI) VM.sysWrite("JNI called: CallStaticFloatMethod \n"); 3224 RuntimeEntrypoints.checkJNICountDownToGC(); 3225 3226 try { 3227 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Float); 3228 return Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value 3229 } catch (Throwable unexpected) { 3230 if (traceJNI) unexpected.printStackTrace(System.err); 3231 env.recordException(unexpected); 3232 return 0f; 3233 } 3234 } 3235 3236 /** 3237 * CallStaticFloatMethodV: invoke a static method that returns a float value 3238 * @param env A JREF index for the JNI environment object 3239 * @param classJREF a JREF index for the class object 3240 * @param methodID id of a MethodReference 3241 * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words 3242 * of the appropriate type for the method invocation 3243 * @return the float value returned from the method invocation 3244 */ 3245 private static float CallStaticFloatMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3246 throws Exception { 3247 if (traceJNI) VM.sysWrite("JNI called: CallStaticFloatMethodV \n"); 3248 RuntimeEntrypoints.checkJNICountDownToGC(); 3249 3250 try { 3251 Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Float); 3252 return Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value 3253 } catch (Throwable unexpected) { 3254 if (traceJNI) unexpected.printStackTrace(System.err); 3255 env.recordException(unexpected); 3256 return 0f; 3257 } 3258 } 3259 3260 /** 3261 * CallStaticFloatMethodA: invoke a static method that returns a float value 3262 * @param env A JREF index for the JNI environment object 3263 * @param classJREF a JREF index for the class object 3264 * @param methodID id of a MethodReference 3265 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 3266 * of the appropriate type for the method invocation 3267 * @return the float value returned from the method invocation 3268 */ 3269 private static float CallStaticFloatMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3270 throws Exception { 3271 if (traceJNI) VM.sysWrite("JNI called: CallStaticFloatMethodA \n"); 3272 RuntimeEntrypoints.checkJNICountDownToGC(); 3273 3274 try { 3275 Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Float); 3276 return Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value 3277 } catch (Throwable unexpected) { 3278 if (traceJNI) unexpected.printStackTrace(System.err); 3279 env.recordException(unexpected); 3280 return 0f; 3281 } 3282 } 3283 3284 /** 3285 * CallStaticDoubleMethod: invoke a static method that returns a double value 3286 * arguments passed using the vararg ... style 3287 * NOTE: the vararg's are not visible in the method signature here; they are saved 3288 * in the caller frame and the glue frame 3289 * @param env A JREF index for the JNI environment object 3290 * @param classJREF a JREF index for the class object 3291 * @param methodID an id of a MethodReference 3292 * @return the double value returned from the method invocation 3293 */ 3294 private static double CallStaticDoubleMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 3295 if (traceJNI) VM.sysWrite("JNI called: CallStaticDoubleMethod \n"); 3296 RuntimeEntrypoints.checkJNICountDownToGC(); 3297 3298 try { 3299 Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Double); 3300 return Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value 3301 } catch (Throwable unexpected) { 3302 if (traceJNI) unexpected.printStackTrace(System.err); 3303 env.recordException(unexpected); 3304 return 0; 3305 } 3306 } 3307 3308 /** 3309 * CallStaticDoubleMethodV: invoke a static method that returns a double value 3310 * @param env A JREF index for the JNI environment object 3311 * @param classJREF a JREF index for the class object 3312 * @param methodID an id of a MethodReference 3313 * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words 3314 * of the appropriate type for the method invocation 3315 * @return the double value returned from the method invocation 3316 */ 3317 private static double CallStaticDoubleMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3318 throws Exception { 3319 if (traceJNI) VM.sysWrite("JNI called: CallStaticDoubleMethodV \n"); 3320 RuntimeEntrypoints.checkJNICountDownToGC(); 3321 3322 try { 3323 Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Double); 3324 return Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value 3325 } catch (Throwable unexpected) { 3326 if (traceJNI) unexpected.printStackTrace(System.err); 3327 env.recordException(unexpected); 3328 return 0; 3329 } 3330 } 3331 3332 /** 3333 * CallStaticDoubleMethodA: invoke a static method that returns a double value 3334 * @param env A JREF index for the JNI environment object 3335 * @param classJREF a JREF index for the class object 3336 * @param methodID id of a MethodReference 3337 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 3338 * of the appropriate type for the method invocation 3339 * @return the double value returned from the method invocation 3340 */ 3341 private static double CallStaticDoubleMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3342 throws Exception { 3343 if (traceJNI) VM.sysWrite("JNI called: CallStaticDoubleMethodA \n"); 3344 RuntimeEntrypoints.checkJNICountDownToGC(); 3345 3346 try { 3347 Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Double); 3348 return Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value 3349 } catch (Throwable unexpected) { 3350 if (traceJNI) unexpected.printStackTrace(System.err); 3351 env.recordException(unexpected); 3352 return 0; 3353 } 3354 } 3355 3356 /** 3357 * CallStaticVoidMethod: invoke a static method that returns void 3358 * arguments passed using the vararg ... style 3359 * NOTE: the vararg's are not visible in the method signature here; they are saved 3360 * in the caller frame and the glue frame 3361 * @param env A JREF index for the JNI environment object 3362 * @param classJREF a JREF index for the class object 3363 * @param methodID id of a MethodReference 3364 */ 3365 private static void CallStaticVoidMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception { 3366 if (traceJNI) VM.sysWrite("JNI called: CallStaticVoidMethod \n"); 3367 RuntimeEntrypoints.checkJNICountDownToGC(); 3368 3369 try { 3370 JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Void); 3371 } catch (Throwable unexpected) { 3372 if (traceJNI) unexpected.printStackTrace(System.err); 3373 env.recordException(unexpected); 3374 } 3375 } 3376 3377 /** 3378 * CallStaticVoidMethodA: invoke a static method that returns void 3379 * @param env A JREF index for the JNI environment object 3380 * @param classJREF a JREF index for the class object 3381 * @param methodID id of a MethodReference 3382 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 3383 * of the appropriate type for the method invocation 3384 */ 3385 private static void CallStaticVoidMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3386 throws Exception { 3387 if (traceJNI) VM.sysWrite("JNI called: CallStaticVoidMethodV \n"); 3388 RuntimeEntrypoints.checkJNICountDownToGC(); 3389 3390 try { 3391 JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Void); 3392 } catch (Throwable unexpected) { 3393 if (traceJNI) unexpected.printStackTrace(System.err); 3394 env.recordException(unexpected); 3395 } 3396 } 3397 3398 /** 3399 * CallStaticVoidMethodA: invoke a static method that returns void 3400 * @param env A JREF index for the JNI environment object 3401 * @param classJREF a JREF index for the class object 3402 * @param methodID id of a MethodReference 3403 * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument 3404 * of the appropriate type for the method invocation 3405 */ 3406 private static void CallStaticVoidMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress) 3407 throws Exception { 3408 if (traceJNI) VM.sysWrite("JNI called: CallStaticVoidMethodA \n"); 3409 RuntimeEntrypoints.checkJNICountDownToGC(); 3410 3411 try { 3412 JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Void); 3413 } catch (Throwable unexpected) { 3414 if (traceJNI) unexpected.printStackTrace(System.err); 3415 env.recordException(unexpected); 3416 } 3417 } 3418 3419 /** 3420 * GetStaticFieldID: return a field id which can be cached in native code and reused 3421 * @param env A JREF index for the JNI environment object 3422 * @param classJREF a JREF index for the RVMClass object 3423 * @param fieldNameAddress a raw address to a null-terminated string in C for the field name 3424 * @param descriptorAddress a raw address to a null-terminated string in C for the descriptor 3425 * @return the offset of a static field given the class, field name 3426 * and type. Return 0 if the field is not found 3427 * @exception NoSuchFieldError if the specified field cannot be found 3428 * @exception ExceptionInInitializerError if the class initializer fails 3429 * @exception OutOfMemoryError if the system runs out of memory 3430 */ 3431 private static int GetStaticFieldID(JNIEnvironment env, int classJREF, Address fieldNameAddress, 3432 Address descriptorAddress) { 3433 if (traceJNI) VM.sysWrite("JNI called: GetStaticFieldID \n"); 3434 RuntimeEntrypoints.checkJNICountDownToGC(); 3435 3436 try { 3437 Class<?> cls = (Class<?>) env.getJNIRef(classJREF); 3438 3439 String fieldString = JNIHelpers.createStringFromC(fieldNameAddress); 3440 Atom fieldName = Atom.findOrCreateAsciiAtom(fieldString); 3441 String descriptorString = JNIHelpers.createStringFromC(descriptorAddress); 3442 Atom descriptor = Atom.findOrCreateAsciiAtom(descriptorString); 3443 3444 RVMType rvmType = java.lang.JikesRVMSupport.getTypeForClass(cls); 3445 if (rvmType.isClassType()) { 3446 // First search for the fields in the class and its superclasses 3447 for (RVMClass curClass = rvmType.asClass(); curClass != null; curClass = curClass.getSuperClass()) { 3448 for (RVMField field : curClass.getStaticFields()) { 3449 if (field.getName() == fieldName && field.getDescriptor() == descriptor) { 3450 return field.getId(); 3451 } 3452 } 3453 } 3454 // Now search all implemented interfaces (includes inherited interfaces) 3455 for (RVMClass curClass : rvmType.asClass().getAllImplementedInterfaces()) { 3456 for (RVMField field : curClass.getStaticFields()) { 3457 if (field.getName() == fieldName && field.getDescriptor() == descriptor) { 3458 return field.getId(); 3459 } 3460 } 3461 } 3462 } 3463 3464 env.recordException(new NoSuchFieldError(fieldString + ", " + descriptorString + " of " + cls)); 3465 return 0; 3466 } catch (Throwable unexpected) { 3467 if (traceJNI) unexpected.printStackTrace(System.err); 3468 env.recordException(unexpected); 3469 return 0; 3470 } 3471 } 3472 3473 /** 3474 * GetStaticObjectField: read a static field of type Object 3475 * @param env A JREF index for the JNI environment object 3476 * @param classJREF a JREF index for the RVMClass object 3477 * @param fieldID the id for the RVMField that describes this field 3478 * @return the value of the Object field, converted to a JREF index 3479 * or 0 if the fieldID is incorrect 3480 */ 3481 private static int GetStaticObjectField(JNIEnvironment env, int classJREF, int fieldID) { 3482 if (traceJNI) VM.sysWrite("JNI called: GetStaticObjectField \n"); 3483 RuntimeEntrypoints.checkJNICountDownToGC(); 3484 3485 try { 3486 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3487 Object value = field.getObjectUnchecked(null); 3488 return env.pushJNIRef(value); 3489 } catch (Throwable unexpected) { 3490 if (traceJNI) unexpected.printStackTrace(System.err); 3491 env.recordException(unexpected); 3492 return 0; 3493 } 3494 } 3495 3496 /** 3497 * GetStaticBooleanField: read a static field of type boolean 3498 * @param env A JREF index for the JNI environment object 3499 * @param classJREF a JREF index for the RVMClass object 3500 * @param fieldID the id for the RVMField that describes this field 3501 * @return the value of the boolean field, or 0 if the fieldID is incorrect 3502 */ 3503 private static int GetStaticBooleanField(JNIEnvironment env, int classJREF, int fieldID) { 3504 if (traceJNI) VM.sysWrite("JNI called: GetStaticBooleanField \n"); 3505 RuntimeEntrypoints.checkJNICountDownToGC(); 3506 3507 try { 3508 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3509 return field.getBooleanValueUnchecked(null) ? 1 : 0; 3510 } catch (Throwable unexpected) { 3511 if (traceJNI) unexpected.printStackTrace(System.err); 3512 env.recordException(unexpected); 3513 return 0; 3514 } 3515 } 3516 3517 /** 3518 * GetStaticByteField: read a static field of type byte 3519 * @param env A JREF index for the JNI environment object 3520 * @param classJREF a JREF index for the RVMClass object 3521 * @param fieldID the id for the RVMField that describes this field 3522 * @return the value of the byte field, or 0 if the fieldID is incorrect 3523 */ 3524 private static int GetStaticByteField(JNIEnvironment env, int classJREF, int fieldID) { 3525 if (traceJNI) VM.sysWrite("JNI called: GetStaticByteField \n"); 3526 RuntimeEntrypoints.checkJNICountDownToGC(); 3527 3528 try { 3529 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3530 return field.getByteValueUnchecked(null); 3531 } catch (Throwable unexpected) { 3532 if (traceJNI) unexpected.printStackTrace(System.err); 3533 env.recordException(unexpected); 3534 return 0; 3535 } 3536 } 3537 3538 /** 3539 * GetStaticCharField: read a static field of type character 3540 * @param env A JREF index for the JNI environment object 3541 * @param classJREF a JREF index for the RVMClass object 3542 * @param fieldID the id for the RVMField that describes this field 3543 * @return the value of the character field, or 0 if the fieldID is incorrect 3544 */ 3545 private static int GetStaticCharField(JNIEnvironment env, int classJREF, int fieldID) { 3546 if (traceJNI) VM.sysWrite("JNI called: GetStaticCharField \n"); 3547 RuntimeEntrypoints.checkJNICountDownToGC(); 3548 3549 try { 3550 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3551 return field.getCharValueUnchecked(null); 3552 } catch (Throwable unexpected) { 3553 if (traceJNI) unexpected.printStackTrace(System.err); 3554 env.recordException(unexpected); 3555 return 0; 3556 } 3557 } 3558 3559 /** 3560 * GetStaticShortField: read a static field of type short 3561 * @param env A JREF index for the JNI environment object 3562 * @param classJREF a JREF index for the RVMClass object 3563 * @param fieldID the id for the RVMField that describes this field 3564 * @return the value of the short field, or 0 if the fieldID is incorrect 3565 */ 3566 private static int GetStaticShortField(JNIEnvironment env, int classJREF, int fieldID) { 3567 if (traceJNI) VM.sysWrite("JNI called: GetStaticShortField \n"); 3568 RuntimeEntrypoints.checkJNICountDownToGC(); 3569 3570 try { 3571 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3572 return field.getShortValueUnchecked(null); 3573 } catch (Throwable unexpected) { 3574 if (traceJNI) unexpected.printStackTrace(System.err); 3575 env.recordException(unexpected); 3576 return 0; 3577 } 3578 } 3579 3580 /** 3581 * GetStaticIntField: read a static field of type integer 3582 * @param env A JREF index for the JNI environment object 3583 * @param classJREF a JREF index for the RVMClass object 3584 * @param fieldID the id for the RVMField that describes this field 3585 * @return the value of the integer field, or 0 if the fieldID is incorrect 3586 */ 3587 private static int GetStaticIntField(JNIEnvironment env, int classJREF, int fieldID) { 3588 if (traceJNI) VM.sysWrite("JNI called: GetStaticIntField \n"); 3589 RuntimeEntrypoints.checkJNICountDownToGC(); 3590 3591 try { 3592 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3593 return field.getIntValueUnchecked(null); 3594 } catch (Throwable unexpected) { 3595 if (traceJNI) unexpected.printStackTrace(System.err); 3596 env.recordException(unexpected); 3597 return 0; 3598 } 3599 } 3600 3601 /** 3602 * GetStaticLongField: read a static field of type long 3603 * @param env A JREF index for the JNI environment object 3604 * @param classJREF a JREF index for the RVMClass object 3605 * @param fieldID the id for the RVMField that describes this field 3606 * @return the value of the long field or 0 if the fieldID is incorrect 3607 */ 3608 private static long GetStaticLongField(JNIEnvironment env, int classJREF, int fieldID) { 3609 if (traceJNI) VM.sysWrite("JNI called: GetStaticLongField \n"); 3610 RuntimeEntrypoints.checkJNICountDownToGC(); 3611 3612 try { 3613 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3614 return field.getLongValueUnchecked(null); 3615 } catch (Throwable unexpected) { 3616 if (traceJNI) unexpected.printStackTrace(System.err); 3617 env.recordException(unexpected); 3618 return 0; 3619 } 3620 } 3621 3622 /** 3623 * GetStaticFloatField: read a static field of type float 3624 * @param env A JREF index for the JNI environment object 3625 * @param classJREF a JREF index for the RVMClass object 3626 * @param fieldID the id for the RVMField that describes this field 3627 * @return the value of the float field or 0 if the fieldID is incorrect 3628 */ 3629 private static float GetStaticFloatField(JNIEnvironment env, int classJREF, int fieldID) { 3630 if (traceJNI) VM.sysWrite("JNI called: GetStaticFloatField \n"); 3631 RuntimeEntrypoints.checkJNICountDownToGC(); 3632 3633 try { 3634 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3635 return field.getFloatValueUnchecked(null); 3636 } catch (Throwable unexpected) { 3637 if (traceJNI) unexpected.printStackTrace(System.err); 3638 env.recordException(unexpected); 3639 return 0; 3640 } 3641 } 3642 3643 /** 3644 * GetStaticDoubleField: read a static field of type double 3645 * @param env A JREF index for the JNI environment object 3646 * @param classJREF a JREF index for the RVMClass object 3647 * @param fieldID the id for the RVMField that describes this field 3648 * @return the value of the double field or 0 if the fieldID is incorrect 3649 */ 3650 private static double GetStaticDoubleField(JNIEnvironment env, int classJREF, int fieldID) { 3651 if (traceJNI) VM.sysWrite("JNI called: GetStaticDoubleField \n"); 3652 RuntimeEntrypoints.checkJNICountDownToGC(); 3653 3654 try { 3655 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3656 return field.getDoubleValueUnchecked(null); 3657 } catch (Throwable unexpected) { 3658 if (traceJNI) unexpected.printStackTrace(System.err); 3659 env.recordException(unexpected); 3660 return 0; 3661 } 3662 } 3663 3664 /** 3665 * SetStaticObjectField: set a static field of type Object 3666 * @param env A JREF index for the JNI environment object 3667 * @param classJREF A JREF index for the {@link RVMClass} object 3668 * @param fieldID The id for the {@link RVMField} that describes this 3669 * field 3670 * @param objectJREF A JREF index of the value to assign 3671 */ 3672 private static void SetStaticObjectField(JNIEnvironment env, int classJREF, int fieldID, int objectJREF) { 3673 if (traceJNI) VM.sysWrite("JNI called: SetStaticObjectField \n"); 3674 RuntimeEntrypoints.checkJNICountDownToGC(); 3675 3676 try { 3677 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3678 Object ref = env.getJNIRef(objectJREF); 3679 field.setObjectValueUnchecked(null, ref); 3680 } catch (Throwable unexpected) { 3681 if (traceJNI) unexpected.printStackTrace(System.err); 3682 env.recordException(unexpected); 3683 } 3684 } 3685 3686 /** 3687 * SetStaticBooleanField: set a static field of type boolean 3688 * @param env A JREF index for the JNI environment object 3689 * @param classJREF A JREF index for the RVMClass object 3690 * @param fieldID the id for the RVMField that describes this field 3691 * @param fieldValue The value to assign 3692 */ 3693 private static void SetStaticBooleanField(JNIEnvironment env, int classJREF, int fieldID, boolean fieldValue) { 3694 if (traceJNI) VM.sysWrite("JNI called: SetStaticBooleanField \n"); 3695 RuntimeEntrypoints.checkJNICountDownToGC(); 3696 3697 try { 3698 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3699 field.setBooleanValueUnchecked(null, fieldValue); 3700 } catch (Throwable unexpected) { 3701 if (traceJNI) unexpected.printStackTrace(System.err); 3702 env.recordException(unexpected); 3703 } 3704 } 3705 3706 /** 3707 * SetStaticByteField: set a static field of type byte 3708 * @param env A JREF index for the JNI environment object 3709 * @param classJREF a JREF index for the RVMClass object 3710 * @param fieldID the id for the RVMField that describes this field 3711 * @param fieldValue the value to assign 3712 */ 3713 private static void SetStaticByteField(JNIEnvironment env, int classJREF, int fieldID, byte fieldValue) { 3714 if (traceJNI) VM.sysWrite("JNI called: SetStaticByteField \n"); 3715 RuntimeEntrypoints.checkJNICountDownToGC(); 3716 3717 try { 3718 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3719 field.setByteValueUnchecked(null, fieldValue); 3720 } catch (Throwable unexpected) { 3721 if (traceJNI) unexpected.printStackTrace(System.err); 3722 env.recordException(unexpected); 3723 } 3724 } 3725 3726 /** 3727 * SetStaticCharField: set a static field of type char 3728 * @param env A JREF index for the JNI environment object 3729 * @param classJREF a JREF index for the RVMClass object 3730 * @param fieldID the id for the RVMField that describes this field 3731 * @param fieldValue The value to assign 3732 */ 3733 private static void SetStaticCharField(JNIEnvironment env, int classJREF, int fieldID, char fieldValue) { 3734 if (traceJNI) VM.sysWrite("JNI called: SetStaticCharField \n"); 3735 RuntimeEntrypoints.checkJNICountDownToGC(); 3736 3737 try { 3738 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3739 field.setCharValueUnchecked(null, fieldValue); 3740 } catch (Throwable unexpected) { 3741 if (traceJNI) unexpected.printStackTrace(System.err); 3742 env.recordException(unexpected); 3743 } 3744 } 3745 3746 /** 3747 * SetStaticShortField: set a static field of type short 3748 * @param env A JREF index for the JNI environment object 3749 * @param classJREF a JREF index for the RVMClass object 3750 * @param fieldID the id for the RVMField that describes this field 3751 * @param fieldValue The value to assign 3752 */ 3753 private static void SetStaticShortField(JNIEnvironment env, int classJREF, int fieldID, short fieldValue) { 3754 if (traceJNI) VM.sysWrite("JNI called: SetStaticShortField \n"); 3755 RuntimeEntrypoints.checkJNICountDownToGC(); 3756 3757 try { 3758 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3759 field.setShortValueUnchecked(null, fieldValue); 3760 } catch (Throwable unexpected) { 3761 if (traceJNI) unexpected.printStackTrace(System.err); 3762 env.recordException(unexpected); 3763 } 3764 } 3765 3766 /** 3767 * SetStaticIntField: set a static field of type integer 3768 * @param env A JREF index for the JNI environment object 3769 * @param classJREF a JREF index for the RVMClass object 3770 * @param fieldID the id for the RVMField that describes this field 3771 * @param fieldValue The value to assign 3772 */ 3773 private static void SetStaticIntField(JNIEnvironment env, int classJREF, int fieldID, int fieldValue) { 3774 if (traceJNI) VM.sysWrite("JNI called: SetStaticIntField \n"); 3775 RuntimeEntrypoints.checkJNICountDownToGC(); 3776 3777 try { 3778 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3779 field.setIntValueUnchecked(null, fieldValue); 3780 } catch (Throwable unexpected) { 3781 if (traceJNI) unexpected.printStackTrace(System.err); 3782 env.recordException(unexpected); 3783 } 3784 } 3785 3786 /** 3787 * SetStaticLongField: set a static field of type long 3788 * @param env A JREF index for the JNI environment object 3789 * @param classJREF a JREF index for the RVMClass object 3790 * @param fieldID the id for the RVMField that describes this field 3791 * @param fieldValue The value to assign 3792 */ 3793 private static void SetStaticLongField(JNIEnvironment env, int classJREF, int fieldID, long fieldValue) { 3794 if (traceJNI) VM.sysWrite("JNI called: SetStaticLongField \n"); 3795 RuntimeEntrypoints.checkJNICountDownToGC(); 3796 3797 try { 3798 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3799 field.setLongValueUnchecked(null, fieldValue); 3800 } catch (Throwable unexpected) { 3801 if (traceJNI) unexpected.printStackTrace(System.err); 3802 env.recordException(unexpected); 3803 } 3804 } 3805 3806 /** 3807 * SetStaticFloatField: set a static field of type float 3808 * @param env A JREF index for the JNI environment object 3809 * @param classJREF a JREF index for the RVMClass object 3810 * @param fieldID the id for the RVMField that describes this field 3811 * @param fieldValue The value to assign 3812 */ 3813 private static void SetStaticFloatField(JNIEnvironment env, int classJREF, int fieldID, float fieldValue) { 3814 if (traceJNI) VM.sysWrite("JNI called: SetStaticFloatField \n"); 3815 RuntimeEntrypoints.checkJNICountDownToGC(); 3816 3817 try { 3818 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3819 field.setFloatValueUnchecked(null, fieldValue); 3820 } catch (Throwable unexpected) { 3821 if (traceJNI) unexpected.printStackTrace(System.err); 3822 env.recordException(unexpected); 3823 } 3824 } 3825 3826 /** 3827 * SetStaticDoubleField: set a static field of type float 3828 * @param env A JREF index for the JNI environment object 3829 * @param classJREF a JREF index for the RVMClass object 3830 * @param fieldID the id for the RVMField that describes this field 3831 * @param fieldValue The value to assign 3832 */ 3833 private static void SetStaticDoubleField(JNIEnvironment env, int classJREF, int fieldID, double fieldValue) { 3834 if (traceJNI) VM.sysWrite("JNI called: SetStaticDoubleField \n"); 3835 RuntimeEntrypoints.checkJNICountDownToGC(); 3836 3837 try { 3838 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 3839 field.setDoubleValueUnchecked(null, fieldValue); 3840 } catch (Throwable unexpected) { 3841 if (traceJNI) unexpected.printStackTrace(System.err); 3842 env.recordException(unexpected); 3843 } 3844 } 3845 3846 /** 3847 * NewString: create a String Object from C array of unicode chars 3848 * @param env A JREF index for the JNI environment object 3849 * @param uchars address of C array of 16 bit unicode characters 3850 * @param len the number of chars in the C array 3851 * @return the allocated String Object, converted to a JREF index 3852 * or 0 if an OutOfMemoryError Exception has been thrown 3853 * @exception OutOfMemoryError 3854 */ 3855 private static int NewString(JNIEnvironment env, Address uchars, int len) { 3856 if (traceJNI) VM.sysWrite("JNI called: NewString \n"); 3857 RuntimeEntrypoints.checkJNICountDownToGC(); 3858 3859 try { 3860 final char[] contents = new char[len]; 3861 Memory.memcopy(Magic.objectAsAddress(contents), uchars, len * 2); 3862 return env.pushJNIRef(java.lang.JikesRVMSupport.newStringWithoutCopy(contents, 0, len)); 3863 } catch (Throwable unexpected) { 3864 if (traceJNI) unexpected.printStackTrace(System.err); 3865 env.recordException(unexpected); 3866 return 0; 3867 } 3868 } 3869 3870 /** 3871 * GetStringLength: return the length of a String 3872 * @param env A JREF index for the JNI environment object 3873 * @param objJREF a JREF index for the String object 3874 * @return the length of the String 3875 */ 3876 private static int GetStringLength(JNIEnvironment env, int objJREF) { 3877 if (traceJNI) VM.sysWrite("JNI called: GetStringLength \n"); 3878 RuntimeEntrypoints.checkJNICountDownToGC(); 3879 3880 try { 3881 String str = (String) env.getJNIRef(objJREF); 3882 return str.length(); 3883 } catch (Throwable unexpected) { 3884 if (traceJNI) unexpected.printStackTrace(System.err); 3885 env.recordException(unexpected); 3886 return 0; 3887 } 3888 } 3889 3890 /** 3891 * GetStringChars: return address of buffer containing contents of a String 3892 * @param env A JREF index for the JNI environment object 3893 * @param strJREF a JREF index for the String object 3894 * @param isCopyAddress address of isCopy jboolean (an int) 3895 * @return address of a copy of the String unicode characters 3896 * and *isCopy is set to 1 (TRUE) 3897 * @exception OutOfMemoryError if the system runs out of memory 3898 */ 3899 private static Address GetStringChars(JNIEnvironment env, int strJREF, Address isCopyAddress) { 3900 if (traceJNI) VM.sysWrite("JNI called: GetStringChars \n"); 3901 RuntimeEntrypoints.checkJNICountDownToGC(); 3902 3903 String str = (String) env.getJNIRef(strJREF); 3904 char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str); 3905 int strOffset = java.lang.JikesRVMSupport.getStringOffset(str); 3906 int len = java.lang.JikesRVMSupport.getStringLength(str); 3907 3908 // alloc non moving buffer in C heap for a copy of string contents 3909 Address copyBuffer = sysCall.sysMalloc(len * 2); 3910 if (copyBuffer.isZero()) { 3911 env.recordException(new OutOfMemoryError()); 3912 return Address.zero(); 3913 } 3914 try { 3915 Address strBase = Magic.objectAsAddress(strChars); 3916 Address srcBase = strBase.plus(strOffset * 2); 3917 Memory.memcopy(copyBuffer, srcBase, len * 2); 3918 3919 /* Set caller's isCopy boolean to true, if we got a valid (non-null) 3920 address */ 3921 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 3922 3923 return copyBuffer; 3924 } catch (Throwable unexpected) { 3925 if (traceJNI) unexpected.printStackTrace(System.err); 3926 env.recordException(unexpected); 3927 sysCall.sysFree(copyBuffer); 3928 return Address.zero(); 3929 } 3930 } 3931 3932 /** 3933 * ReleaseStringChars: release buffer obtained via GetStringChars 3934 * @param env A JREF index for the JNI environment object 3935 * @param objJREF a JREF index for the String object 3936 * @param bufAddress address of buffer to release 3937 */ 3938 private static void ReleaseStringChars(JNIEnvironment env, int objJREF, Address bufAddress) { 3939 if (traceJNI) VM.sysWrite("JNI called: ReleaseStringChars \n"); 3940 RuntimeEntrypoints.checkJNICountDownToGC(); 3941 3942 try { 3943 sysCall.sysFree(bufAddress); 3944 } catch (Throwable unexpected) { 3945 if (traceJNI) unexpected.printStackTrace(System.err); 3946 env.recordException(unexpected); 3947 } 3948 } 3949 3950 /** 3951 * NewStringUTF: create a String Object from C array of utf8 bytes 3952 * @param env A JREF index for the JNI environment object 3953 * @param utf8bytes address of C array of 8 bit utf8 bytes 3954 * @return the allocated String Object, converted to a JREF index 3955 * or 0 if an OutOfMemoryError Exception has been thrown 3956 * @exception OutOfMemoryError if the system runs out of memory 3957 */ 3958 private static int NewStringUTF(JNIEnvironment env, Address utf8bytes) { 3959 if (traceJNI) VM.sysWrite("JNI called: NewStringUTF \n"); 3960 RuntimeEntrypoints.checkJNICountDownToGC(); 3961 3962 try { 3963 String returnString = JNIHelpers.createUTFStringFromC(utf8bytes); 3964 return env.pushJNIRef(returnString); 3965 } catch (Throwable unexpected) { 3966 if (traceJNI) unexpected.printStackTrace(System.err); 3967 env.recordException(unexpected); 3968 return 0; 3969 } 3970 } 3971 3972 /** 3973 * GetStringUTFLength: return number of bytes to represent a String in UTF8 format 3974 * @param env A JREF index for the JNI environment object 3975 * @param objJREF a JREF index for the String object 3976 * @return number of bytes to represent in UTF8 format 3977 */ 3978 private static int GetStringUTFLength(JNIEnvironment env, int objJREF) { 3979 if (traceJNI) VM.sysWrite("JNI called: GetStringUTFLength \n"); 3980 RuntimeEntrypoints.checkJNICountDownToGC(); 3981 3982 try { 3983 String str = (String) env.getJNIRef(objJREF); 3984 return UTF8Convert.utfLength(str); 3985 } catch (Throwable unexpected) { 3986 if (traceJNI) unexpected.printStackTrace(System.err); 3987 env.recordException(unexpected); 3988 return 0; 3989 } 3990 } 3991 3992 /** 3993 * GetStringUTFChars: return address of buffer containing contents of a String 3994 * @param env A JREF index for the JNI environment object 3995 * @param strJREF a JREF index for the String object 3996 * @param isCopyAddress address of isCopy jboolean (an int) 3997 * @return address of a copy of the String unicode characters 3998 * and *isCopy is set to 1 (TRUE) 3999 * @exception OutOfMemoryError if the system runs out of memory 4000 */ 4001 private static Address GetStringUTFChars(JNIEnvironment env, int strJREF, Address isCopyAddress) { 4002 if (traceJNI) VM.sysWrite("JNI called: GetStringUTFChars \n"); 4003 RuntimeEntrypoints.checkJNICountDownToGC(); 4004 4005 String str = (String) env.getJNIRef(strJREF); 4006 4007 // Get length of C string 4008 int len = UTF8Convert.utfLength(str) + 1; // for terminating zero 4009 4010 // alloc non moving buffer in C heap for string 4011 Address copyBuffer = sysCall.sysMalloc(len); 4012 if (copyBuffer.isZero()) { 4013 env.recordException(new OutOfMemoryError()); 4014 return Address.zero(); 4015 } 4016 try { 4017 JNIHelpers.createUTFForCFromString(str, copyBuffer, len); 4018 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 4019 return copyBuffer; 4020 } catch (Throwable unexpected) { 4021 if (traceJNI) unexpected.printStackTrace(System.err); 4022 env.recordException(unexpected); 4023 return Address.zero(); 4024 } 4025 } 4026 4027 /** 4028 * ReleaseStringUTFChars: release buffer obtained via GetStringUTFChars 4029 * @param env A JREF index for the JNI environment object 4030 * @param objJREF a JREF index for the String object 4031 * @param bufAddress address of buffer to release 4032 */ 4033 private static void ReleaseStringUTFChars(JNIEnvironment env, int objJREF, Address bufAddress) { 4034 if (traceJNI) VM.sysWrite("JNI called: ReleaseStringUTFChars \n"); 4035 RuntimeEntrypoints.checkJNICountDownToGC(); 4036 4037 try { 4038 sysCall.sysFree(bufAddress); 4039 } catch (Throwable unexpected) { 4040 if (traceJNI) unexpected.printStackTrace(System.err); 4041 env.recordException(unexpected); 4042 } 4043 } 4044 4045 /** 4046 * GetArrayLength: return array length 4047 * @param env A JREF index for the JNI environment object 4048 * @param arrayJREF a JREF index for the source array 4049 * @return the array length, or -1 if it's not an array 4050 */ 4051 private static int GetArrayLength(JNIEnvironment env, int arrayJREF) { 4052 if (traceJNI) VM.sysWrite("JNI called: GetArrayLength \n"); 4053 RuntimeEntrypoints.checkJNICountDownToGC(); 4054 4055 try { 4056 Object theArray = env.getJNIRef(arrayJREF); 4057 RVMType arrayType = Magic.getObjectType(theArray); 4058 return arrayType.isArrayType() ? Magic.getArrayLength(theArray) : -1; 4059 } catch (Throwable unexpected) { 4060 if (traceJNI) unexpected.printStackTrace(System.err); 4061 env.recordException(unexpected); 4062 return -1; 4063 } 4064 } 4065 4066 /** 4067 * NewObjectArray: create a new Object array 4068 * @param env A JREF index for the JNI environment object 4069 * @param length the size of the new array 4070 * @param classJREF a JREF index for the class of the element 4071 * @param initElementJREF a JREF index for the value to initialize the array elements 4072 * @return the new Object array initialized 4073 * @exception OutOfMemoryError if the system runs out of memory 4074 */ 4075 private static int NewObjectArray(JNIEnvironment env, int length, int classJREF, int initElementJREF) { 4076 if (traceJNI) VM.sysWrite("JNI called: NewObjectArray \n"); 4077 RuntimeEntrypoints.checkJNICountDownToGC(); 4078 4079 try { 4080 Object initElement = env.getJNIRef(initElementJREF); 4081 Class<?> cls = (Class<?>) env.getJNIRef(classJREF); 4082 4083 if (cls == null) { 4084 throw new NullPointerException(); 4085 } 4086 if (length < 0) { 4087 throw new NegativeArraySizeException(); 4088 } 4089 4090 RVMArray arrayType = java.lang.JikesRVMSupport.getTypeForClass(cls).getArrayTypeForElementType(); 4091 if (!arrayType.isInitialized()) { 4092 arrayType.resolve(); 4093 arrayType.instantiate(); 4094 arrayType.initialize(); 4095 } 4096 Object[] newArray = (Object[]) RuntimeEntrypoints.resolvedNewArray(length, arrayType); 4097 4098 if (initElement != null) { 4099 for (int i = 0; i < length; i++) { 4100 newArray[i] = initElement; 4101 } 4102 } 4103 4104 return env.pushJNIRef(newArray); 4105 } catch (Throwable unexpected) { 4106 if (traceJNI) unexpected.printStackTrace(System.err); 4107 env.recordException(unexpected); 4108 return 0; 4109 } 4110 } 4111 4112 /** 4113 * GetObjectArrayElement: retrieve an object from an object array 4114 * @param env A JREF index for the JNI environment object 4115 * @param arrayJREF a JREF index for the source array 4116 * @param index the index for the targeted element 4117 * @return the object at the specified index 4118 * @exception ArrayIndexOutOfBoundsException if the index is out of range 4119 */ 4120 private static int GetObjectArrayElement(JNIEnvironment env, int arrayJREF, int index) { 4121 if (traceJNI) VM.sysWrite("JNI called: GetObjectArrayElement \n"); 4122 RuntimeEntrypoints.checkJNICountDownToGC(); 4123 4124 try { 4125 Object[] sourceArray = (Object[]) env.getJNIRef(arrayJREF); 4126 4127 if (sourceArray == null) { 4128 return 0; 4129 } 4130 4131 RVMArray arrayType = Magic.getObjectType(sourceArray).asArray(); 4132 RVMType elementType = arrayType.getElementType(); 4133 if (elementType.isPrimitiveType() || elementType.isUnboxedType()) { 4134 return 0; 4135 } 4136 4137 if (index >= Magic.getArrayLength(sourceArray)) { 4138 env.recordException(new ArrayIndexOutOfBoundsException()); 4139 return 0; 4140 } 4141 4142 return env.pushJNIRef(sourceArray[index]); 4143 } catch (Throwable unexpected) { 4144 if (traceJNI) unexpected.printStackTrace(System.err); 4145 env.recordException(unexpected); 4146 return 0; 4147 } 4148 } 4149 4150 /** 4151 * SetObjectArrayElement: store an object into an object array 4152 * @param env A JREF index for the JNI environment object 4153 * @param arrayJREF a JREF index for the source array 4154 * @param index the index for the targeted element 4155 * @param objectJREF a JREF index for the object to store into the array 4156 * @exception ArrayStoreException if the element types do not match 4157 * ArrayIndexOutOfBoundsException if the index is out of range 4158 */ 4159 private static void SetObjectArrayElement(JNIEnvironment env, int arrayJREF, int index, int objectJREF) { 4160 if (traceJNI) VM.sysWrite("JNI called: SetObjectArrayElement \n"); 4161 RuntimeEntrypoints.checkJNICountDownToGC(); 4162 4163 try { 4164 Object[] sourceArray = (Object[]) env.getJNIRef(arrayJREF); 4165 Object elem = env.getJNIRef(objectJREF); 4166 sourceArray[index] = elem; 4167 } catch (Throwable e) { 4168 env.recordException(e); 4169 } 4170 } 4171 4172 /** 4173 * NewBooleanArray: create a new boolean array 4174 * @param env A JREF index for the JNI environment object 4175 * @param length the size of the new array 4176 * @return the new boolean array 4177 * @exception OutOfMemoryError if the system runs out of memory 4178 */ 4179 private static int NewBooleanArray(JNIEnvironment env, int length) { 4180 if (traceJNI) VM.sysWrite("JNI called: NewBooleanArray \n"); 4181 RuntimeEntrypoints.checkJNICountDownToGC(); 4182 4183 try { 4184 boolean[] newArray = new boolean[length]; 4185 return env.pushJNIRef(newArray); 4186 } catch (Throwable unexpected) { 4187 if (traceJNI) unexpected.printStackTrace(System.err); 4188 env.recordException(unexpected); 4189 return 0; 4190 } 4191 } 4192 4193 /** 4194 * NewByteArray: create a new byte array 4195 * @param env A JREF index for the JNI environment object 4196 * @param length the size of the new array 4197 * @return the new byte array 4198 * @exception OutOfMemoryError if the system runs out of memory 4199 */ 4200 private static int NewByteArray(JNIEnvironment env, int length) { 4201 if (traceJNI) VM.sysWrite("JNI called: NewByteArray \n"); 4202 RuntimeEntrypoints.checkJNICountDownToGC(); 4203 4204 try { 4205 byte[] newArray = new byte[length]; 4206 return env.pushJNIRef(newArray); 4207 } catch (Throwable unexpected) { 4208 if (traceJNI) unexpected.printStackTrace(System.err); 4209 env.recordException(unexpected); 4210 return 0; 4211 } 4212 } 4213 4214 /** 4215 * NewCharArray: create a new char array 4216 * @param env A JREF index for the JNI environment object 4217 * @param length the size of the new array 4218 * @return the new char array 4219 * @exception OutOfMemoryError if the system runs out of memory 4220 */ 4221 private static int NewCharArray(JNIEnvironment env, int length) { 4222 if (traceJNI) VM.sysWrite("JNI called: NewCharArray \n"); 4223 RuntimeEntrypoints.checkJNICountDownToGC(); 4224 4225 try { 4226 char[] newArray = new char[length]; 4227 return env.pushJNIRef(newArray); 4228 } catch (Throwable unexpected) { 4229 if (traceJNI) unexpected.printStackTrace(System.err); 4230 env.recordException(unexpected); 4231 return 0; 4232 } 4233 } 4234 4235 /** 4236 * NewShortArray: create a new short array 4237 * @param env A JREF index for the JNI environment object 4238 * @param length the size of the new array 4239 * @return the new short array 4240 * @exception OutOfMemoryError if the system runs out of memory 4241 */ 4242 private static int NewShortArray(JNIEnvironment env, int length) { 4243 if (traceJNI) VM.sysWrite("JNI called: NewShortArray \n"); 4244 RuntimeEntrypoints.checkJNICountDownToGC(); 4245 4246 try { 4247 short[] newArray = new short[length]; 4248 return env.pushJNIRef(newArray); 4249 } catch (Throwable unexpected) { 4250 if (traceJNI) unexpected.printStackTrace(System.err); 4251 env.recordException(unexpected); 4252 return 0; 4253 } 4254 } 4255 4256 /** 4257 * NewIntArray: create a new integer array 4258 * @param env A JREF index for the JNI environment object 4259 * @param length the size of the new array 4260 * @return the new integer array 4261 * @exception OutOfMemoryError if the system runs out of memory 4262 */ 4263 private static int NewIntArray(JNIEnvironment env, int length) { 4264 if (traceJNI) VM.sysWrite("JNI called: NewIntArray \n"); 4265 RuntimeEntrypoints.checkJNICountDownToGC(); 4266 4267 try { 4268 int[] newArray = new int[length]; 4269 return env.pushJNIRef(newArray); 4270 } catch (Throwable unexpected) { 4271 if (traceJNI) unexpected.printStackTrace(System.err); 4272 env.recordException(unexpected); 4273 return 0; 4274 } 4275 } 4276 4277 /** 4278 * NewLongArray: create a new long array 4279 * @param env A JREF index for the JNI environment object 4280 * @param length the size of the new array 4281 * @return the new long array 4282 * @exception OutOfMemoryError if the system runs out of memory 4283 */ 4284 private static int NewLongArray(JNIEnvironment env, int length) { 4285 if (traceJNI) VM.sysWrite("JNI called: NewLongArray \n"); 4286 RuntimeEntrypoints.checkJNICountDownToGC(); 4287 4288 try { 4289 long[] newArray = new long[length]; 4290 return env.pushJNIRef(newArray); 4291 } catch (Throwable unexpected) { 4292 if (traceJNI) unexpected.printStackTrace(System.err); 4293 env.recordException(unexpected); 4294 return 0; 4295 } 4296 } 4297 4298 /** 4299 * NewFloatArray: create a new float array 4300 * @param env A JREF index for the JNI environment object 4301 * @param length the size of the new array 4302 * @return the new float array 4303 * @exception OutOfMemoryError if the system runs out of memory 4304 */ 4305 private static int NewFloatArray(JNIEnvironment env, int length) { 4306 if (traceJNI) VM.sysWrite("JNI called: NewFloatArray \n"); 4307 RuntimeEntrypoints.checkJNICountDownToGC(); 4308 4309 try { 4310 float[] newArray = new float[length]; 4311 return env.pushJNIRef(newArray); 4312 } catch (Throwable unexpected) { 4313 if (traceJNI) unexpected.printStackTrace(System.err); 4314 env.recordException(unexpected); 4315 return 0; 4316 } 4317 } 4318 4319 /** 4320 * NewDoubleArray: create a new double array 4321 * @param env A JREF index for the JNI environment object 4322 * @param length the size of the new array 4323 * @return the new long array 4324 * @exception OutOfMemoryError if the system runs out of memory 4325 */ 4326 private static int NewDoubleArray(JNIEnvironment env, int length) { 4327 if (traceJNI) VM.sysWrite("JNI called: NewDoubleArray \n"); 4328 RuntimeEntrypoints.checkJNICountDownToGC(); 4329 4330 try { 4331 double[] newArray = new double[length]; 4332 return env.pushJNIRef(newArray); 4333 } catch (Throwable unexpected) { 4334 if (traceJNI) unexpected.printStackTrace(System.err); 4335 env.recordException(unexpected); 4336 return 0; 4337 } 4338 } 4339 4340 /** 4341 * GetBooleanArrayElements: get all the elements of a boolean array 4342 * @param env A JREF index for the JNI environment object 4343 * @param arrayJREF a JREF index for the source array 4344 * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer 4345 * @return A pointer to the boolean array and the isCopy flag is set to true if it's a copy 4346 * or false if it's a direct pointer 4347 * @exception OutOfMemoryError if the system runs out of memory 4348 */ 4349 private static Address GetBooleanArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) { 4350 if (traceJNI) VM.sysWrite("JNI called: GetBooleanArrayElements \n"); 4351 RuntimeEntrypoints.checkJNICountDownToGC(); 4352 4353 try { 4354 boolean[] sourceArray = (boolean[]) env.getJNIRef(arrayJREF); 4355 int size = sourceArray.length; 4356 4357 // alloc non moving buffer in C heap for a copy of string contents 4358 Address copyBuffer = sysCall.sysMalloc(size); 4359 if (copyBuffer.isZero()) { 4360 env.recordException(new OutOfMemoryError()); 4361 return Address.zero(); 4362 } 4363 4364 Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size); 4365 4366 /* Set caller's isCopy boolean to true, if we got a valid (non-null) 4367 address */ 4368 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 4369 4370 return copyBuffer; 4371 } catch (Throwable unexpected) { 4372 if (traceJNI) unexpected.printStackTrace(System.err); 4373 env.recordException(unexpected); 4374 return Address.zero(); 4375 } 4376 } 4377 4378 /** 4379 * GetByteArrayElements: get all the elements of a byte array 4380 * @param env A JREF index for the JNI environment object 4381 * @param arrayJREF a JREF index for the source array 4382 * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer 4383 * @return A pointer to the byte array and the isCopy flag is set to true if it's a copy 4384 * or false if it's a direct pointer 4385 * @exception OutOfMemoryError if the system runs out of memory 4386 */ 4387 private static Address GetByteArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) { 4388 if (traceJNI) VM.sysWrite("JNI called: GetByteArrayElements \n"); 4389 RuntimeEntrypoints.checkJNICountDownToGC(); 4390 4391 try { 4392 byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF); 4393 int size = sourceArray.length; 4394 4395 if (MemoryManager.willNeverMove(sourceArray)) { 4396 /* return a direct pointer */ 4397 JNIGenericHelpers.setBoolStar(isCopyAddress, false); 4398 return Magic.objectAsAddress(sourceArray); 4399 } else { 4400 // alloc non moving buffer in C heap for a copy of string contents 4401 Address copyBuffer = sysCall.sysMalloc(size); 4402 4403 if (copyBuffer.isZero()) { 4404 env.recordException(new OutOfMemoryError()); 4405 return Address.zero(); 4406 } 4407 4408 Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size); 4409 4410 /* Set caller's isCopy boolean to true, if we got a valid (non-null) 4411 address */ 4412 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 4413 4414 return copyBuffer; 4415 } 4416 } catch (Throwable unexpected) { 4417 if (traceJNI) unexpected.printStackTrace(System.err); 4418 env.recordException(unexpected); 4419 return Address.zero(); 4420 } 4421 } 4422 4423 /** 4424 * GetCharArrayElements: get all the elements of a char array 4425 * @param env A JREF index for the JNI environment object 4426 * @param arrayJREF a JREF index for the source array 4427 * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer 4428 * @return A pointer to the char array and the isCopy flag is set to true if it's a copy 4429 * or false if it's a direct pointer 4430 * @exception OutOfMemoryError if the system runs out of memory 4431 */ 4432 private static Address GetCharArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) { 4433 if (traceJNI) VM.sysWrite("JNI called: GetCharArrayElements \n"); 4434 RuntimeEntrypoints.checkJNICountDownToGC(); 4435 4436 try { 4437 char[] sourceArray = (char[]) env.getJNIRef(arrayJREF); 4438 int size = sourceArray.length; 4439 4440 if (MemoryManager.willNeverMove(sourceArray)) { 4441 JNIGenericHelpers.setBoolStar(isCopyAddress, false); 4442 return Magic.objectAsAddress(sourceArray); 4443 } else { 4444 // alloc non moving buffer in C heap for a copy of string contents 4445 Address copyBuffer = sysCall.sysMalloc(size * BYTES_IN_CHAR); 4446 if (copyBuffer.isZero()) { 4447 env.recordException(new OutOfMemoryError()); 4448 return Address.zero(); 4449 } 4450 4451 Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size * BYTES_IN_CHAR); 4452 4453 /* Set caller's isCopy boolean to true, if we got a valid (non-null) 4454 address */ 4455 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 4456 4457 return copyBuffer; 4458 } 4459 } catch (Throwable unexpected) { 4460 if (traceJNI) unexpected.printStackTrace(System.err); 4461 env.recordException(unexpected); 4462 return Address.zero(); 4463 } 4464 } 4465 4466 /** 4467 * GetShortArrayElements: get all the elements of a short array 4468 * @param env A JREF index for the JNI environment object 4469 * @param arrayJREF a JREF index for the source array 4470 * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer 4471 * @return A pointer to the short array and the isCopy flag is set to true if it's a copy 4472 * or false if it's a direct pointer 4473 * @exception OutOfMemoryError if the system runs out of memory 4474 */ 4475 private static Address GetShortArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) { 4476 if (traceJNI) VM.sysWrite("JNI called: GetShortArrayElements \n"); 4477 RuntimeEntrypoints.checkJNICountDownToGC(); 4478 4479 try { 4480 short[] sourceArray = (short[]) env.getJNIRef(arrayJREF); 4481 int size = sourceArray.length; 4482 4483 if (MemoryManager.willNeverMove(sourceArray)) { 4484 JNIGenericHelpers.setBoolStar(isCopyAddress, false); 4485 return Magic.objectAsAddress(sourceArray); 4486 } else { 4487 // alloc non moving buffer in C heap for a copy of string contents 4488 Address copyBuffer = sysCall.sysMalloc(size * BYTES_IN_SHORT); 4489 if (copyBuffer.isZero()) { 4490 env.recordException(new OutOfMemoryError()); 4491 return Address.zero(); 4492 } 4493 4494 Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size * BYTES_IN_SHORT); 4495 4496 /* Set caller's isCopy boolean to true, if we got a valid (non-null) 4497 address */ 4498 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 4499 4500 return copyBuffer; 4501 } 4502 } catch (Throwable unexpected) { 4503 if (traceJNI) unexpected.printStackTrace(System.err); 4504 env.recordException(unexpected); 4505 return Address.zero(); 4506 } 4507 } 4508 4509 /** 4510 * GetIntArrayElements: get all the elements of an integer array 4511 * @param env A JREF index for the JNI environment object 4512 * @param arrayJREF a JREF index for the source array 4513 * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer 4514 * @return A pointer to the integer array and the isCopy flag is set to true if it's a copy 4515 * or false if it's a direct pointer 4516 * @exception OutOfMemoryError if the system runs out of memory 4517 */ 4518 private static Address GetIntArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) { 4519 if (traceJNI) VM.sysWrite("JNI called: GetIntArrayElements \n"); 4520 RuntimeEntrypoints.checkJNICountDownToGC(); 4521 4522 try { 4523 int[] sourceArray = (int[]) env.getJNIRef(arrayJREF); 4524 int size = sourceArray.length; 4525 4526 if (MemoryManager.willNeverMove(sourceArray)) { 4527 JNIGenericHelpers.setBoolStar(isCopyAddress, false); 4528 return Magic.objectAsAddress(sourceArray); 4529 } else { 4530 // alloc non moving buffer in C heap for a copy of array contents 4531 Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_INT); 4532 if (copyBuffer.isZero()) { 4533 env.recordException(new OutOfMemoryError()); 4534 return Address.zero(); 4535 } 4536 Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_INT); 4537 4538 /* Set caller's isCopy boolean to true, if we got a valid (non-null) 4539 address */ 4540 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 4541 4542 return copyBuffer; 4543 } 4544 } catch (Throwable unexpected) { 4545 if (traceJNI) unexpected.printStackTrace(System.err); 4546 env.recordException(unexpected); 4547 return Address.zero(); 4548 } 4549 } 4550 4551 /** 4552 * GetLongArrayElements: get all the elements of a long array 4553 * @param env A JREF index for the JNI environment object 4554 * @param arrayJREF a JREF index for the source array 4555 * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer 4556 * @return A pointer to the long array and the isCopy flag is set to true if it's a copy 4557 * or false if it's a direct pointer 4558 * @exception OutOfMemoryError if the system runs out of memory 4559 */ 4560 private static Address GetLongArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) { 4561 if (traceJNI) VM.sysWrite("JNI called: GetLongArrayElements \n"); 4562 RuntimeEntrypoints.checkJNICountDownToGC(); 4563 4564 try { 4565 long[] sourceArray = (long[]) env.getJNIRef(arrayJREF); 4566 int size = sourceArray.length; 4567 4568 if (MemoryManager.willNeverMove(sourceArray)) { 4569 JNIGenericHelpers.setBoolStar(isCopyAddress, false); 4570 return Magic.objectAsAddress(sourceArray); 4571 } else { 4572 // alloc non moving buffer in C heap for a copy of string contents 4573 Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_LONG); 4574 if (copyBuffer.isZero()) { 4575 env.recordException(new OutOfMemoryError()); 4576 return Address.zero(); 4577 } 4578 Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_LONG); 4579 4580 /* Set caller's isCopy boolean to true, if we got a valid (non-null) 4581 address */ 4582 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 4583 4584 return copyBuffer; 4585 } 4586 } catch (Throwable unexpected) { 4587 if (traceJNI) unexpected.printStackTrace(System.err); 4588 env.recordException(unexpected); 4589 return Address.zero(); 4590 } 4591 } 4592 4593 /** 4594 * GetFloatArrayElements: get all the elements of a float array 4595 * @param env A JREF index for the JNI environment object 4596 * @param arrayJREF a JREF index for the source array 4597 * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer 4598 * @return A pointer to the float array and the isCopy flag is set to true if it's a copy 4599 * or false if it's a direct pointer 4600 * @exception OutOfMemoryError if the system runs out of memory 4601 */ 4602 private static Address GetFloatArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) { 4603 if (traceJNI) VM.sysWrite("JNI called: GetFloatArrayElements \n"); 4604 RuntimeEntrypoints.checkJNICountDownToGC(); 4605 4606 try { 4607 float[] sourceArray = (float[]) env.getJNIRef(arrayJREF); 4608 int size = sourceArray.length; 4609 4610 if (MemoryManager.willNeverMove(sourceArray)) { 4611 JNIGenericHelpers.setBoolStar(isCopyAddress, false); 4612 return Magic.objectAsAddress(sourceArray); 4613 } else { 4614 // alloc non moving buffer in C heap for a copy of string contents 4615 Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_FLOAT); 4616 if (copyBuffer.isZero()) { 4617 env.recordException(new OutOfMemoryError()); 4618 return Address.zero(); 4619 } 4620 4621 Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_FLOAT); 4622 4623 /* Set caller's isCopy boolean to true, if we got a valid (non-null) 4624 address */ 4625 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 4626 4627 return copyBuffer; 4628 } 4629 } catch (Throwable unexpected) { 4630 if (traceJNI) unexpected.printStackTrace(System.err); 4631 env.recordException(unexpected); 4632 return Address.zero(); 4633 } 4634 } 4635 4636 /** 4637 * GetDoubleArrayElements: get all the elements of a double array 4638 * @param env A JREF index for the JNI environment object 4639 * @param arrayJREF a JREF index for the source array 4640 * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer 4641 * @return A pointer to the double array and the isCopy flag is set to true if it's a copy 4642 * or false if it's a direct pointer 4643 * @exception OutOfMemoryError if the system runs out of memory 4644 */ 4645 private static Address GetDoubleArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) { 4646 if (traceJNI) VM.sysWrite("JNI called: GetDoubleArrayElements \n"); 4647 RuntimeEntrypoints.checkJNICountDownToGC(); 4648 4649 try { 4650 double[] sourceArray = (double[]) env.getJNIRef(arrayJREF); 4651 int size = sourceArray.length; 4652 4653 if (MemoryManager.willNeverMove(sourceArray)) { 4654 JNIGenericHelpers.setBoolStar(isCopyAddress, false); 4655 return Magic.objectAsAddress(sourceArray); 4656 } else { 4657 // alloc non moving buffer in C heap for a copy of string contents 4658 Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_DOUBLE); 4659 if (copyBuffer.isZero()) { 4660 env.recordException(new OutOfMemoryError()); 4661 return Address.zero(); 4662 } 4663 Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_DOUBLE); 4664 4665 /* Set caller's isCopy boolean to true, if we got a valid (non-null) 4666 address */ 4667 JNIGenericHelpers.setBoolStar(isCopyAddress, true); 4668 4669 return copyBuffer; 4670 } 4671 } catch (Throwable unexpected) { 4672 if (traceJNI) unexpected.printStackTrace(System.err); 4673 env.recordException(unexpected); 4674 return Address.zero(); 4675 } 4676 } 4677 4678 /** 4679 * ReleaseBooleanArrayElements: free the native copy of the array, update changes to Java array as indicated 4680 * @param env A JREF index for the JNI environment object 4681 * @param arrayJREF a JREF index for the source array 4682 * @param copyBufferAddress the address of the copy of the array 4683 * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: 4684 * releaseMode 0: copy back and free the buffer 4685 * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer 4686 * releaseMode 2: JNI_ABORT, free the buffer with copying back 4687 */ 4688 private static void ReleaseBooleanArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress, 4689 int releaseMode) { 4690 if (traceJNI) VM.sysWrite("JNI called: ReleaseBooleanArrayElements \n"); 4691 RuntimeEntrypoints.checkJNICountDownToGC(); 4692 4693 try { 4694 boolean[] sourceArray = (boolean[]) env.getJNIRef(arrayJREF); 4695 4696 // If a direct pointer was given to the user, no need to update or release 4697 if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { 4698 int size = sourceArray.length; 4699 4700 // mode 0 and mode 1: copy back the buffer 4701 if ((releaseMode == 0 || releaseMode == 1) && size != 0) { 4702 for (int i = 0; i < size; i += BYTES_IN_INT) { 4703 Address addr = copyBufferAddress.plus(i); 4704 int data = addr.loadInt(); 4705 if (VM.LittleEndian) { 4706 if (i < size) sourceArray[i] = ((data) & 0x000000ff) != 0; 4707 if (i + 1 < size) sourceArray[i + 1] = ((data >>> BITS_IN_BYTE) & 0x000000ff) != 0; 4708 if (i + 2 < size) sourceArray[i + 2] = ((data >>> (2 * BITS_IN_BYTE)) & 0x000000ff) != 0; 4709 if (i + 3 < size) sourceArray[i + 3] = ((data >>> (3 * BITS_IN_BYTE)) & 0x000000ff) != 0; 4710 } else { 4711 if (i < size) sourceArray[i] = ((data >>> (3 * BITS_IN_BYTE)) & 0x000000ff) != 0; 4712 if (i + 1 < size) sourceArray[i + 1] = ((data >>> (2 * BITS_IN_BYTE)) & 0x000000ff) != 0; 4713 if (i + 2 < size) sourceArray[i + 2] = ((data >>> BITS_IN_BYTE) & 0x000000ff) != 0; 4714 if (i + 3 < size) sourceArray[i + 3] = ((data) & 0x000000ff) != 0; 4715 } 4716 } 4717 } 4718 4719 // mode 0 and mode 2: free the buffer 4720 if (releaseMode == 0 || releaseMode == 2) { 4721 sysCall.sysFree(copyBufferAddress); 4722 } 4723 } 4724 } catch (Throwable unexpected) { 4725 if (traceJNI) unexpected.printStackTrace(System.err); 4726 env.recordException(unexpected); 4727 } 4728 } 4729 4730 /** 4731 * ReleaseByteArrayElements: free the native copy of the array, update changes to Java array as indicated 4732 * @param env A JREF index for the JNI environment object 4733 * @param arrayJREF a JREF index for the source array 4734 * @param copyBufferAddress the address of the copy of the array 4735 * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: 4736 * releaseMode 0: copy back and free the buffer 4737 * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer 4738 * releaseMode 2: JNI_ABORT, free the buffer with copying back 4739 */ 4740 private static void ReleaseByteArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress, 4741 int releaseMode) { 4742 if (traceJNI) VM.sysWrite("JNI called: ReleaseByteArrayElements releaseMode=", releaseMode); 4743 RuntimeEntrypoints.checkJNICountDownToGC(); 4744 4745 try { 4746 byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF); 4747 4748 // If a direct pointer was given to the user, no need to update or release 4749 if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { 4750 int size = sourceArray.length; 4751 if (traceJNI) VM.sysWrite(" size=", size); 4752 4753 // mode 0 and mode 1: copy back the buffer 4754 if ((releaseMode == 0 || releaseMode == 1) && size != 0) { 4755 Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size); 4756 } 4757 4758 // mode 0 and mode 2: free the buffer 4759 if (releaseMode == 0 || releaseMode == 2) { 4760 sysCall.sysFree(copyBufferAddress); 4761 } 4762 } else { 4763 // Nothing to be done 4764 } 4765 } catch (Throwable unexpected) { 4766 if (traceJNI) unexpected.printStackTrace(System.err); 4767 env.recordException(unexpected); 4768 } 4769 if (traceJNI) VM.sysWrite("\n"); 4770 } 4771 4772 /** 4773 * ReleaseCharArrayElements: free the native copy of the array, update changes to Java array as indicated 4774 * @param env A JREF index for the JNI environment object 4775 * @param arrayJREF a JREF index for the source array 4776 * @param copyBufferAddress the address of the copy of the array 4777 * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: 4778 * releaseMode 0: copy back and free the buffer 4779 * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer 4780 * releaseMode 2: JNI_ABORT, free the buffer with copying back 4781 */ 4782 private static void ReleaseCharArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress, 4783 int releaseMode) { 4784 if (traceJNI) VM.sysWrite("JNI called: ReleaseCharArrayElements \n"); 4785 RuntimeEntrypoints.checkJNICountDownToGC(); 4786 4787 try { 4788 char[] sourceArray = (char[]) env.getJNIRef(arrayJREF); 4789 4790 // If a direct pointer was given to the user, no need to update or release 4791 if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { 4792 int size = sourceArray.length; 4793 4794 // mode 0 and mode 1: copy back the buffer 4795 if ((releaseMode == 0 || releaseMode == 1) && size != 0) { 4796 Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_CHAR); 4797 } 4798 4799 // mode 0 and mode 2: free the buffer 4800 if (releaseMode == 0 || releaseMode == 2) { 4801 sysCall.sysFree(copyBufferAddress); 4802 } 4803 } 4804 } catch (Throwable unexpected) { 4805 if (traceJNI) unexpected.printStackTrace(System.err); 4806 env.recordException(unexpected); 4807 } 4808 } 4809 4810 /** 4811 * ReleaseShortArrayElements: free the native copy of the array, update changes to Java array as indicated 4812 * @param env A JREF index for the JNI environment object 4813 * @param arrayJREF a JREF index for the source array 4814 * @param copyBufferAddress the address of the copy of the array 4815 * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: 4816 * releaseMode 0: copy back and free the buffer 4817 * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer 4818 * releaseMode 2: JNI_ABORT, free the buffer with copying back 4819 */ 4820 private static void ReleaseShortArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress, 4821 int releaseMode) { 4822 if (traceJNI) VM.sysWrite("JNI called: ReleaseShortArrayElements \n"); 4823 RuntimeEntrypoints.checkJNICountDownToGC(); 4824 4825 try { 4826 short[] sourceArray = (short[]) env.getJNIRef(arrayJREF); 4827 4828 // If a direct pointer was given to the user, no need to update or release 4829 if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { 4830 int size = sourceArray.length; 4831 4832 // mode 0 and mode 1: copy back the buffer 4833 if ((releaseMode == 0 || releaseMode == 1) && size != 0) { 4834 Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_SHORT); 4835 } 4836 4837 // mode 0 and mode 2: free the buffer 4838 if (releaseMode == 0 || releaseMode == 2) { 4839 sysCall.sysFree(copyBufferAddress); 4840 } 4841 } 4842 } catch (Throwable unexpected) { 4843 if (traceJNI) unexpected.printStackTrace(System.err); 4844 env.recordException(unexpected); 4845 } 4846 } 4847 4848 /** 4849 * ReleaseIntArrayElements: free the native copy of the array, update changes to Java array as indicated 4850 * @param env A JREF index for the JNI environment object 4851 * @param arrayJREF a JREF index for the source array 4852 * @param copyBufferAddress the address of the copy of the array 4853 * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: 4854 * releaseMode 0: copy back and free the buffer 4855 * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer 4856 * releaseMode 2: JNI_ABORT, free the buffer with copying back 4857 */ 4858 private static void ReleaseIntArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress, 4859 int releaseMode) { 4860 if (traceJNI) VM.sysWrite("JNI called: ReleaseIntArrayElements \n"); 4861 RuntimeEntrypoints.checkJNICountDownToGC(); 4862 4863 try { 4864 int[] sourceArray = (int[]) env.getJNIRef(arrayJREF); 4865 4866 // If a direct pointer was given to the user, no need to update or release 4867 if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { 4868 int size = sourceArray.length; 4869 4870 // mode 0 and mode 1: copy back the buffer 4871 if (releaseMode == 0 || releaseMode == 1) { 4872 Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_INT); 4873 } 4874 4875 // mode 0 and mode 2: free the buffer 4876 if (releaseMode == 0 || releaseMode == 2) { 4877 sysCall.sysFree(copyBufferAddress); 4878 } 4879 } 4880 } catch (Throwable unexpected) { 4881 if (traceJNI) unexpected.printStackTrace(System.err); 4882 env.recordException(unexpected); 4883 } 4884 } 4885 4886 /** 4887 * ReleaseLongArrayElements: free the native copy of the array, update changes to Java array as indicated 4888 * @param env A JREF index for the JNI environment object 4889 * @param arrayJREF a JREF index for the source array 4890 * @param copyBufferAddress the address of the copy of the array 4891 * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: 4892 * releaseMode 0: copy back and free the buffer 4893 * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer 4894 * releaseMode 2: JNI_ABORT, free the buffer with copying back 4895 */ 4896 private static void ReleaseLongArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress, 4897 int releaseMode) { 4898 if (traceJNI) VM.sysWrite("JNI called: ReleaseLongArrayElements \n"); 4899 RuntimeEntrypoints.checkJNICountDownToGC(); 4900 4901 try { 4902 long[] sourceArray = (long[]) env.getJNIRef(arrayJREF); 4903 4904 // If a direct pointer was given to the user, no need to update or release 4905 if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { 4906 int size = sourceArray.length; 4907 4908 // mode 0 and mode 1: copy back the buffer 4909 if (releaseMode == 0 || releaseMode == 1) { 4910 Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_LONG); 4911 } 4912 4913 // mode 0 and mode 2: free the buffer 4914 if (releaseMode == 0 || releaseMode == 2) { 4915 sysCall.sysFree(copyBufferAddress); 4916 } 4917 } 4918 } catch (Throwable unexpected) { 4919 if (traceJNI) unexpected.printStackTrace(System.err); 4920 env.recordException(unexpected); 4921 } 4922 } 4923 4924 /** 4925 * ReleaseFloatArrayElements: free the native copy of the array, update changes to Java array as indicated 4926 * @param env A JREF index for the JNI environment object 4927 * @param arrayJREF a JREF index for the source array 4928 * @param copyBufferAddress the address of the copy of the array 4929 * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: 4930 * releaseMode 0: copy back and free the buffer 4931 * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer 4932 * releaseMode 2: JNI_ABORT, free the buffer with copying back 4933 */ 4934 private static void ReleaseFloatArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress, 4935 int releaseMode) { 4936 if (traceJNI) VM.sysWrite("JNI called: ReleaseFloatArrayElements \n"); 4937 RuntimeEntrypoints.checkJNICountDownToGC(); 4938 4939 try { 4940 float[] sourceArray = (float[]) env.getJNIRef(arrayJREF); 4941 4942 // If a direct pointer was given to the user, no need to update or release 4943 if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { 4944 int size = sourceArray.length; 4945 4946 // mode 0 and mode 1: copy back the buffer 4947 if (releaseMode == 0 || releaseMode == 1) { 4948 Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_FLOAT); 4949 } 4950 4951 // mode 0 and mode 2: free the buffer 4952 if (releaseMode == 0 || releaseMode == 2) { 4953 sysCall.sysFree(copyBufferAddress); 4954 } 4955 } 4956 } catch (Throwable unexpected) { 4957 if (traceJNI) unexpected.printStackTrace(System.err); 4958 env.recordException(unexpected); 4959 } 4960 } 4961 4962 /** 4963 * ReleaseDoubleArrayElements: free the native copy of the array, update changes to Java array as indicated 4964 * @param env A JREF index for the JNI environment object 4965 * @param arrayJREF a JREF index for the source array 4966 * @param copyBufferAddress the address of the copy of the array 4967 * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: 4968 * releaseMode 0: copy back and free the buffer 4969 * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer 4970 * releaseMode 2: JNI_ABORT, free the buffer with copying back 4971 */ 4972 private static void ReleaseDoubleArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress, 4973 int releaseMode) { 4974 if (traceJNI) VM.sysWrite("JNI called: ReleaseDoubleArrayElements \n"); 4975 RuntimeEntrypoints.checkJNICountDownToGC(); 4976 4977 try { 4978 double[] sourceArray = (double[]) env.getJNIRef(arrayJREF); 4979 4980 // If a direct pointer was given to the user, no need to update or release 4981 if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { 4982 int size = sourceArray.length; 4983 4984 // mode 0 and mode 1: copy back the buffer 4985 if (releaseMode == 0 || releaseMode == 1) { 4986 Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_DOUBLE); 4987 } 4988 4989 // mode 0 and mode 2: free the buffer 4990 if (releaseMode == 0 || releaseMode == 2) { 4991 sysCall.sysFree(copyBufferAddress); 4992 } 4993 } 4994 } catch (Throwable unexpected) { 4995 if (traceJNI) unexpected.printStackTrace(System.err); 4996 env.recordException(unexpected); 4997 } 4998 } 4999 5000 /** 5001 * GetBooleanArrayRegion: copy a region of the array into the native buffer 5002 * @param env A JREF index for the JNI environment object 5003 * @param arrayJREF a JREF index for the source array 5004 * @param startIndex the starting index to copy 5005 * @param length the number of elements to copy 5006 * @param bufAddress the destination address in native to copy to 5007 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5008 */ 5009 private static void GetBooleanArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5010 Address bufAddress) { 5011 if (traceJNI) VM.sysWrite("JNI called: GetBooleanArrayRegion \n"); 5012 RuntimeEntrypoints.checkJNICountDownToGC(); 5013 5014 try { 5015 boolean[] sourceArray = (boolean[]) env.getJNIRef(arrayJREF); 5016 5017 if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { 5018 env.recordException(new ArrayIndexOutOfBoundsException()); 5019 return; 5020 } 5021 Memory.memcopy(bufAddress, Magic.objectAsAddress(sourceArray).plus(startIndex), length); 5022 } catch (Throwable unexpected) { 5023 if (traceJNI) unexpected.printStackTrace(System.err); 5024 env.recordException(unexpected); 5025 } 5026 } 5027 5028 /** 5029 * GetByteArrayRegion: copy a region of the array into the native buffer 5030 * @param env A JREF index for the JNI environment object 5031 * @param arrayJREF a JREF index for the source array 5032 * @param startIndex the starting index to copy 5033 * @param length the number of elements to copy 5034 * @param bufAddress the destination address in native to copy to 5035 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5036 */ 5037 private static void GetByteArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5038 Address bufAddress) { 5039 if (traceJNI) VM.sysWrite("JNI called: GetByteArrayRegion \n"); 5040 RuntimeEntrypoints.checkJNICountDownToGC(); 5041 5042 try { 5043 byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF); 5044 5045 if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { 5046 env.recordException(new ArrayIndexOutOfBoundsException()); 5047 return; 5048 } 5049 5050 Memory.memcopy(bufAddress, Magic.objectAsAddress(sourceArray).plus(startIndex), length); 5051 } catch (Throwable unexpected) { 5052 if (traceJNI) unexpected.printStackTrace(System.err); 5053 env.recordException(unexpected); 5054 } 5055 } 5056 5057 /** 5058 * GetCharArrayRegion: copy a region of the array into the native buffer 5059 * @param env A JREF index for the JNI environment object 5060 * @param arrayJREF a JREF index for the source array 5061 * @param startIndex the starting index to copy 5062 * @param length the number of elements to copy 5063 * @param bufAddress the destination address in native to copy to 5064 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5065 */ 5066 private static void GetCharArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5067 Address bufAddress) { 5068 if (traceJNI) VM.sysWrite("JNI called: GetCharArrayRegion \n"); 5069 RuntimeEntrypoints.checkJNICountDownToGC(); 5070 5071 try { 5072 char[] sourceArray = (char[]) env.getJNIRef(arrayJREF); 5073 5074 if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { 5075 env.recordException(new ArrayIndexOutOfBoundsException()); 5076 return; 5077 } 5078 5079 Memory.memcopy(bufAddress, 5080 Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_CHAR), 5081 length << LOG_BYTES_IN_CHAR); 5082 } catch (Throwable unexpected) { 5083 if (traceJNI) unexpected.printStackTrace(System.err); 5084 env.recordException(unexpected); 5085 } 5086 } 5087 5088 /** 5089 * GetShortArrayRegion: copy a region of the array into the native buffer 5090 * @param env A JREF index for the JNI environment object 5091 * @param arrayJREF a JREF index for the source array 5092 * @param startIndex the starting index to copy 5093 * @param length the number of elements to copy 5094 * @param bufAddress the destination address in native to copy to 5095 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5096 */ 5097 private static void GetShortArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5098 Address bufAddress) { 5099 if (traceJNI) VM.sysWrite("JNI called: GetShortArrayRegion \n"); 5100 RuntimeEntrypoints.checkJNICountDownToGC(); 5101 5102 try { 5103 short[] sourceArray = (short[]) env.getJNIRef(arrayJREF); 5104 5105 if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { 5106 env.recordException(new ArrayIndexOutOfBoundsException()); 5107 return; 5108 } 5109 5110 Memory.memcopy(bufAddress, 5111 Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_SHORT), 5112 length << LOG_BYTES_IN_SHORT); 5113 } catch (Throwable unexpected) { 5114 if (traceJNI) unexpected.printStackTrace(System.err); 5115 env.recordException(unexpected); 5116 } 5117 } 5118 5119 /** 5120 * GetIntArrayRegion: copy a region of the array into the native buffer 5121 * @param env A JREF index for the JNI environment object 5122 * @param arrayJREF a JREF index for the source array 5123 * @param startIndex the starting index to copy 5124 * @param length the number of elements to copy 5125 * @param bufAddress the destination address in native to copy to 5126 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5127 */ 5128 private static void GetIntArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5129 Address bufAddress) { 5130 if (traceJNI) VM.sysWrite("JNI called: GetIntArrayRegion \n"); 5131 RuntimeEntrypoints.checkJNICountDownToGC(); 5132 5133 try { 5134 int[] sourceArray = (int[]) env.getJNIRef(arrayJREF); 5135 5136 if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { 5137 env.recordException(new ArrayIndexOutOfBoundsException()); 5138 return; 5139 } 5140 5141 Memory.memcopy(bufAddress, 5142 Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_INT), 5143 length << LOG_BYTES_IN_INT); 5144 } catch (Throwable unexpected) { 5145 if (traceJNI) unexpected.printStackTrace(System.err); 5146 env.recordException(unexpected); 5147 } 5148 } 5149 5150 /** 5151 * GetLongArrayRegion: copy a region of the array into the native buffer 5152 * @param env A JREF index for the JNI environment object 5153 * @param arrayJREF a JREF index for the source array 5154 * @param startIndex the starting index to copy 5155 * @param length the number of elements to copy 5156 * @param bufAddress the destination address in native to copy to 5157 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5158 */ 5159 private static void GetLongArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5160 Address bufAddress) { 5161 if (traceJNI) VM.sysWrite("JNI called: GetLongArrayRegion \n"); 5162 RuntimeEntrypoints.checkJNICountDownToGC(); 5163 5164 try { 5165 long[] sourceArray = (long[]) env.getJNIRef(arrayJREF); 5166 5167 if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { 5168 env.recordException(new ArrayIndexOutOfBoundsException()); 5169 return; 5170 } 5171 5172 Memory.memcopy(bufAddress, 5173 Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_LONG), 5174 length << LOG_BYTES_IN_LONG); 5175 } catch (Throwable unexpected) { 5176 if (traceJNI) unexpected.printStackTrace(System.err); 5177 env.recordException(unexpected); 5178 } 5179 } 5180 5181 /** 5182 * GetFloatArrayRegion: copy a region of the array into the native buffer 5183 * @param env A JREF index for the JNI environment object 5184 * @param arrayJREF a JREF index for the source array 5185 * @param startIndex the starting index to copy 5186 * @param length the number of elements to copy 5187 * @param bufAddress the destination address in native to copy to 5188 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5189 */ 5190 private static void GetFloatArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5191 Address bufAddress) { 5192 if (traceJNI) VM.sysWrite("JNI called: GetFloatArrayRegion \n"); 5193 RuntimeEntrypoints.checkJNICountDownToGC(); 5194 5195 try { 5196 float[] sourceArray = (float[]) env.getJNIRef(arrayJREF); 5197 5198 if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { 5199 env.recordException(new ArrayIndexOutOfBoundsException()); 5200 return; 5201 } 5202 5203 Memory.memcopy(bufAddress, 5204 Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_FLOAT), 5205 length << LOG_BYTES_IN_FLOAT); 5206 } catch (Throwable unexpected) { 5207 if (traceJNI) unexpected.printStackTrace(System.err); 5208 env.recordException(unexpected); 5209 } 5210 } 5211 5212 /** 5213 * GetDoubleArrayRegion: copy a region of the array into the native buffer 5214 * @param env A JREF index for the JNI environment object 5215 * @param arrayJREF a JREF index for the source array 5216 * @param startIndex the starting index to copy 5217 * @param length the number of elements to copy 5218 * @param bufAddress the destination address in native to copy to 5219 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5220 */ 5221 private static void GetDoubleArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5222 Address bufAddress) { 5223 if (traceJNI) VM.sysWrite("JNI called: GetDoubleArrayRegion \n"); 5224 RuntimeEntrypoints.checkJNICountDownToGC(); 5225 5226 try { 5227 double[] sourceArray = (double[]) env.getJNIRef(arrayJREF); 5228 5229 if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { 5230 env.recordException(new ArrayIndexOutOfBoundsException()); 5231 return; 5232 } 5233 5234 Memory.memcopy(bufAddress, 5235 Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_DOUBLE), 5236 length << LOG_BYTES_IN_DOUBLE); 5237 } catch (Throwable unexpected) { 5238 if (traceJNI) unexpected.printStackTrace(System.err); 5239 env.recordException(unexpected); 5240 } 5241 } 5242 5243 /** 5244 * SetBooleanArrayRegion: copy a region of the native buffer into the array (1 byte element) 5245 * @param env A JREF index for the JNI environment object 5246 * @param arrayJREF a JREF index for the destination array 5247 * @param startIndex the starting index to copy 5248 * @param length the number of elements to copy 5249 * @param bufAddress the source address in native to copy from 5250 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5251 */ 5252 private static void SetBooleanArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5253 Address bufAddress) { 5254 if (traceJNI) VM.sysWrite("JNI called: SetBooleanArrayRegion \n"); 5255 RuntimeEntrypoints.checkJNICountDownToGC(); 5256 5257 try { 5258 boolean[] destinationArray = (boolean[]) env.getJNIRef(arrayJREF); 5259 5260 if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { 5261 env.recordException(new ArrayIndexOutOfBoundsException()); 5262 return; 5263 } 5264 5265 Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex), bufAddress, length); 5266 } catch (Throwable unexpected) { 5267 if (traceJNI) unexpected.printStackTrace(System.err); 5268 env.recordException(unexpected); 5269 } 5270 } 5271 5272 /** 5273 * SetByteArrayRegion: copy a region of the native buffer into the array (1 byte element) 5274 * @param env A JREF index for the JNI environment object 5275 * @param arrayJREF a JREF index for the destination array 5276 * @param startIndex the starting index to copy 5277 * @param length the number of elements to copy 5278 * @param bufAddress the source address in native to copy from 5279 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5280 */ 5281 private static void SetByteArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5282 Address bufAddress) { 5283 if (traceJNI) VM.sysWrite("JNI called: SetByteArrayRegion \n"); 5284 RuntimeEntrypoints.checkJNICountDownToGC(); 5285 5286 try { 5287 byte[] destinationArray = (byte[]) env.getJNIRef(arrayJREF); 5288 5289 if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { 5290 env.recordException(new ArrayIndexOutOfBoundsException()); 5291 return; 5292 } 5293 5294 Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex), bufAddress, length); 5295 } catch (Throwable unexpected) { 5296 if (traceJNI) unexpected.printStackTrace(System.err); 5297 env.recordException(unexpected); 5298 } 5299 } 5300 5301 /** 5302 * SetCharArrayRegion: copy a region of the native buffer into the array (2 byte element) 5303 * @param env A JREF index for the JNI environment object 5304 * @param arrayJREF a JREF index for the destination array 5305 * @param startIndex the starting index to copy 5306 * @param length the number of elements to copy 5307 * @param bufAddress the source address in native to copy from 5308 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5309 */ 5310 private static void SetCharArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5311 Address bufAddress) { 5312 if (traceJNI) VM.sysWrite("JNI called: SetCharArrayRegion \n"); 5313 RuntimeEntrypoints.checkJNICountDownToGC(); 5314 5315 try { 5316 char[] destinationArray = (char[]) env.getJNIRef(arrayJREF); 5317 5318 if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { 5319 env.recordException(new ArrayIndexOutOfBoundsException()); 5320 return; 5321 } 5322 5323 Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_CHAR), 5324 bufAddress, 5325 length << LOG_BYTES_IN_CHAR); 5326 } catch (Throwable unexpected) { 5327 if (traceJNI) unexpected.printStackTrace(System.err); 5328 env.recordException(unexpected); 5329 } 5330 } 5331 5332 /** 5333 * SetShortArrayRegion: copy a region of the native buffer into the array (2 byte element) 5334 * @param env A JREF index for the JNI environment object 5335 * @param arrayJREF a JREF index for the destination array 5336 * @param startIndex the starting index to copy 5337 * @param length the number of elements to copy 5338 * @param bufAddress the source address in native to copy from 5339 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5340 */ 5341 private static void SetShortArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5342 Address bufAddress) { 5343 if (traceJNI) VM.sysWrite("JNI called: SetShortArrayRegion \n"); 5344 RuntimeEntrypoints.checkJNICountDownToGC(); 5345 5346 try { 5347 short[] destinationArray = (short[]) env.getJNIRef(arrayJREF); 5348 5349 if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { 5350 env.recordException(new ArrayIndexOutOfBoundsException()); 5351 return; 5352 } 5353 5354 Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_SHORT), 5355 bufAddress, 5356 length << LOG_BYTES_IN_SHORT); 5357 } catch (Throwable unexpected) { 5358 if (traceJNI) unexpected.printStackTrace(System.err); 5359 env.recordException(unexpected); 5360 } 5361 } 5362 5363 /** 5364 * SetIntArrayRegion: copy a region of the native buffer into the array 5365 * @param env A JREF index for the JNI environment object 5366 * @param arrayJREF a JREF index for the destination array 5367 * @param startIndex the starting index to copy 5368 * @param length the number of elements to copy 5369 * @param bufAddress the source address in native to copy from 5370 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5371 */ 5372 private static void SetIntArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5373 Address bufAddress) { 5374 if (traceJNI) VM.sysWrite("JNI called: SetIntArrayRegion \n"); 5375 RuntimeEntrypoints.checkJNICountDownToGC(); 5376 5377 try { 5378 int[] destinationArray = (int[]) env.getJNIRef(arrayJREF); 5379 5380 if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { 5381 env.recordException(new ArrayIndexOutOfBoundsException()); 5382 return; 5383 } 5384 5385 Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_INT), 5386 bufAddress, 5387 length << LOG_BYTES_IN_INT); 5388 } catch (Throwable unexpected) { 5389 if (traceJNI) unexpected.printStackTrace(System.err); 5390 env.recordException(unexpected); 5391 } 5392 } 5393 5394 /** 5395 * SetLongArrayRegion: copy a region of the native buffer into the array 5396 * @param env A JREF index for the JNI environment object 5397 * @param arrayJREF a JREF index for the destination array 5398 * @param startIndex the starting index to copy 5399 * @param length the number of elements to copy 5400 * @param bufAddress the source address in native to copy from 5401 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5402 */ 5403 private static void SetLongArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5404 Address bufAddress) { 5405 if (traceJNI) VM.sysWrite("JNI called: SetLongArrayRegion \n"); 5406 RuntimeEntrypoints.checkJNICountDownToGC(); 5407 5408 try { 5409 long[] destinationArray = (long[]) env.getJNIRef(arrayJREF); 5410 5411 if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { 5412 env.recordException(new ArrayIndexOutOfBoundsException()); 5413 return; 5414 } 5415 5416 Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_LONG), 5417 bufAddress, 5418 length << LOG_BYTES_IN_LONG); 5419 } catch (Throwable unexpected) { 5420 if (traceJNI) unexpected.printStackTrace(System.err); 5421 env.recordException(unexpected); 5422 } 5423 } 5424 5425 /** 5426 * SetFloatArrayRegion: copy a region of the native buffer into the array 5427 * @param env A JREF index for the JNI environment object 5428 * @param arrayJREF a JREF index for the destination array 5429 * @param startIndex the starting index to copy 5430 * @param length the number of elements to copy 5431 * @param bufAddress the source address in native to copy from 5432 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5433 */ 5434 private static void SetFloatArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5435 Address bufAddress) { 5436 if (traceJNI) VM.sysWrite("JNI called: SetFloatArrayRegion \n"); 5437 RuntimeEntrypoints.checkJNICountDownToGC(); 5438 5439 try { 5440 float[] destinationArray = (float[]) env.getJNIRef(arrayJREF); 5441 5442 if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { 5443 env.recordException(new ArrayIndexOutOfBoundsException()); 5444 return; 5445 } 5446 5447 Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_FLOAT), 5448 bufAddress, 5449 length << LOG_BYTES_IN_FLOAT); 5450 } catch (Throwable unexpected) { 5451 if (traceJNI) unexpected.printStackTrace(System.err); 5452 env.recordException(unexpected); 5453 } 5454 } 5455 5456 /** 5457 * SetDoubleArrayRegion: copy a region of the native buffer into the array 5458 * @param env A JREF index for the JNI environment object 5459 * @param arrayJREF a JREF index for the destination array 5460 * @param startIndex the starting index to copy 5461 * @param length the number of elements to copy 5462 * @param bufAddress the source address in native to copy from 5463 * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid 5464 */ 5465 private static void SetDoubleArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length, 5466 Address bufAddress) { 5467 if (traceJNI) VM.sysWrite("JNI called: SetDoubleArrayRegion \n"); 5468 RuntimeEntrypoints.checkJNICountDownToGC(); 5469 5470 try { 5471 double[] destinationArray = (double[]) env.getJNIRef(arrayJREF); 5472 5473 if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { 5474 env.recordException(new ArrayIndexOutOfBoundsException()); 5475 return; 5476 } 5477 5478 Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_DOUBLE), 5479 bufAddress, 5480 length << LOG_BYTES_IN_DOUBLE); 5481 } catch (Throwable unexpected) { 5482 if (traceJNI) unexpected.printStackTrace(System.err); 5483 env.recordException(unexpected); 5484 } 5485 } 5486 5487 /** 5488 * RegisterNatives: registers implementation of native methods 5489 * @param env A JREF index for the JNI environment object 5490 * @param classJREF a JREF index for the class to register native methods in 5491 * @param methodsAddress the address of an array of native methods to be registered 5492 * @param nmethods the number of native methods in the array 5493 * @return 0 is successful -1 if failed 5494 * @exception NoSuchMethodError if a specified method cannot be found or is not native 5495 */ 5496 private static int RegisterNatives(JNIEnvironment env, int classJREF, Address methodsAddress, int nmethods) { 5497 if (traceJNI) VM.sysWrite("JNI called: RegisterNatives \n"); 5498 RuntimeEntrypoints.checkJNICountDownToGC(); 5499 5500 try { 5501 // get the target class 5502 Class<?> jcls = (Class<?>) env.getJNIRef(classJREF); 5503 RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls); 5504 if (!type.isClassType()) { 5505 env.recordException(new NoSuchMethodError()); 5506 return 0; 5507 } 5508 5509 RVMClass klass = type.asClass(); 5510 if (!klass.isInitialized()) { 5511 RuntimeEntrypoints.initializeClassForDynamicLink(klass); 5512 } 5513 5514 // Create list of methods and verify them to avoid partial success 5515 NativeMethod[] methods = new NativeMethod[nmethods]; 5516 AddressArray symbols = AddressArray.create(nmethods); 5517 5518 Address curMethod = methodsAddress; 5519 for (int i = 0; i < nmethods; i++) { 5520 String methodString = JNIHelpers.createStringFromC(curMethod.loadAddress()); 5521 Atom methodName = Atom.findOrCreateAsciiAtom(methodString); 5522 String sigString = 5523 JNIHelpers.createStringFromC(curMethod.loadAddress(Offset.fromIntSignExtend(BYTES_IN_ADDRESS))); 5524 Atom sigName = Atom.findOrCreateAsciiAtom(sigString); 5525 5526 // Find the target method 5527 RVMMethod meth = klass.findDeclaredMethod(methodName, sigName); 5528 5529 if (meth == null || !meth.isNative()) { 5530 env.recordException(new NoSuchMethodError(klass + ": " + methodName + " " + sigName)); 5531 return -1; 5532 } 5533 methods[i] = (NativeMethod) meth; 5534 symbols.set(i, curMethod.loadAddress(Offset.fromIntSignExtend(BYTES_IN_ADDRESS * 2))); 5535 curMethod = curMethod.plus(3 * BYTES_IN_ADDRESS); 5536 } 5537 5538 // Register methods 5539 for (int i = 0; i < nmethods; i++) { 5540 methods[i].registerNativeSymbol(symbols.get(i)); 5541 } 5542 5543 return 0; 5544 } catch (Throwable unexpected) { 5545 if (traceJNI) unexpected.printStackTrace(System.err); 5546 env.recordException(unexpected); 5547 return -1; 5548 } 5549 } 5550 5551 /** 5552 * UnregisterNatives: unregisters native methods 5553 * @param env A JREF index for the JNI environment object 5554 * @param classJREF a JREF index for the class to register native methods in 5555 * @return 0 is successful -1 if failed 5556 */ 5557 private static int UnregisterNatives(JNIEnvironment env, int classJREF) { 5558 if (traceJNI) VM.sysWrite("JNI called: UnregisterNatives \n"); 5559 RuntimeEntrypoints.checkJNICountDownToGC(); 5560 5561 try { 5562 5563 // get the target class 5564 Class<?> jcls = (Class<?>) env.getJNIRef(classJREF); 5565 RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls); 5566 if (!type.isClassType()) { 5567 env.recordException(new NoClassDefFoundError()); 5568 return -1; 5569 } 5570 5571 RVMClass klass = type.asClass(); 5572 if (!klass.isInitialized()) { 5573 return 0; 5574 } 5575 5576 klass.unregisterNativeMethods(); 5577 return 0; 5578 } catch (Throwable unexpected) { 5579 if (traceJNI) unexpected.printStackTrace(System.err); 5580 env.recordException(unexpected); 5581 return -1; 5582 } 5583 } 5584 5585 /** 5586 * MonitorEnter 5587 * @param env A JREF index for the JNI environment object 5588 * @param objJREF a JREF index for the object to lock 5589 * @return 0 if the object is locked successfully, -1 if not 5590 */ 5591 private static int MonitorEnter(JNIEnvironment env, int objJREF) { 5592 if (traceJNI) VM.sysWrite("JNI called: MonitorEnter \n"); 5593 RuntimeEntrypoints.checkJNICountDownToGC(); 5594 5595 try { 5596 Object obj = env.getJNIRef(objJREF); 5597 ObjectModel.genericLock(obj); 5598 return 0; 5599 } catch (Throwable unexpected) { 5600 if (traceJNI) unexpected.printStackTrace(System.err); 5601 return -1; 5602 } 5603 } 5604 5605 /** 5606 * MonitorExit 5607 * @param env A JREF index for the JNI environment object 5608 * @param objJREF a JREF index for the object to unlock 5609 * @return 0 if the object is unlocked successfully, -1 if not 5610 */ 5611 private static int MonitorExit(JNIEnvironment env, int objJREF) { 5612 if (traceJNI) VM.sysWrite("JNI called: MonitorExit \n"); 5613 RuntimeEntrypoints.checkJNICountDownToGC(); 5614 5615 try { 5616 Object obj = env.getJNIRef(objJREF); 5617 ObjectModel.genericUnlock(obj); 5618 return 0; 5619 } catch (Throwable unexpected) { 5620 if (traceJNI) unexpected.printStackTrace(System.err); 5621 return -1; 5622 } 5623 } 5624 5625 private static int GetJavaVM(JNIEnvironment env, Address StarStarJavaVM) { 5626 if (traceJNI) VM.sysWrite("JNI called: GetJavaVM \n"); 5627 RuntimeEntrypoints.checkJNICountDownToGC(); 5628 5629 try { 5630 if (traceJNI) VM.sysWriteln(StarStarJavaVM); 5631 Address JavaVM = BootRecord.the_boot_record.sysJavaVM; 5632 StarStarJavaVM.store(JavaVM); 5633 5634 return 0; 5635 } catch (Throwable unexpected) { 5636 if (traceJNI) unexpected.printStackTrace(System.err); 5637 return -1; 5638 } 5639 } 5640 5641 /******************************************************************* 5642 * These functions were added in Java 2 (JNI 1.2) 5643 */ 5644 5645 /** 5646 * FromReflectedMethod 5647 * @param env A JREF index for the JNI environment object 5648 * @param methodJREF a JREF index for the java.lang.reflect.Method or 5649 * java.lang.reflect.Constructor object. 5650 * @return the jmethodID corresponding to methodJREF 5651 */ 5652 private static int FromReflectedMethod(JNIEnvironment env, int methodJREF) { 5653 if (traceJNI) VM.sysWrite("JNI called: FromReflectedMethod \n"); 5654 RuntimeEntrypoints.checkJNICountDownToGC(); 5655 5656 Object methodObj = env.getJNIRef(methodJREF); 5657 RVMMethod meth; 5658 if (methodObj instanceof Constructor) { 5659 meth = java.lang.reflect.JikesRVMSupport.getMethodOf((Constructor<?>) methodObj); 5660 } else { 5661 meth = java.lang.reflect.JikesRVMSupport.getMethodOf((Method) methodObj); 5662 } 5663 5664 if (traceJNI) VM.sysWrite("got method " + meth + "\n"); 5665 return meth.getId(); 5666 } 5667 5668 /** 5669 * FromReflectedField 5670 * @param env A JREF index for the JNI environment object 5671 * @param fieldJREF a JREF index for a java.lang.reflect.Field methodID 5672 * @return the jfieldID corresponding to fieldJREF 5673 * */ 5674 private static int FromReflectedField(JNIEnvironment env, int fieldJREF) { 5675 if (traceJNI) VM.sysWrite("JNI called: FromReflectedField \n"); 5676 RuntimeEntrypoints.checkJNICountDownToGC(); 5677 5678 Field fieldObj = (Field) env.getJNIRef(fieldJREF); 5679 RVMField f = java.lang.reflect.JikesRVMSupport.getFieldOf(fieldObj); 5680 if (traceJNI) VM.sysWrite("got field " + f + "\n"); 5681 return f.getId(); 5682 } 5683 5684 /** 5685 * ToReflectedMethod 5686 * @param env A JREF index for the JNI environment object 5687 * @param clsJREF The JREF index of the class from which methodID was 5688 * derived. 5689 * @param methodID a jmethodID to turn into a reflected method 5690 * @param isStatic argument that is not specified in Sun's JNI 1.2 spec, 5691 * but IS present in the 1.4.2 JDK's implementation! Our 5692 * implementation will just ignore it, in any case. This is a 5693 * good example of why the same entity 5694 * shouldn't get to write both the spec and the reference 5695 * implementation. 5696 * @return a JREF index for the java.lang.reflect.Method or 5697 * java.lang.reflect.Constructor object associated with methodID. 5698 */ 5699 private static int ToReflectedMethod(JNIEnvironment env, int clsJREF, int methodID, boolean isStatic) { 5700 if (traceJNI) VM.sysWrite("JNI called: ToReflectedMethod \n"); 5701 RuntimeEntrypoints.checkJNICountDownToGC(); 5702 5703 RVMMethod targetMethod = MemberReference.getMemberRef(methodID).asMethodReference().resolve(); 5704 Object ret; 5705 if (targetMethod.isObjectInitializer()) { 5706 ret = java.lang.reflect.JikesRVMSupport.createConstructor(targetMethod); 5707 } else { 5708 ret = java.lang.reflect.JikesRVMSupport.createMethod(targetMethod); 5709 } 5710 return env.pushJNIRef(ret); 5711 } 5712 5713 /** 5714 * ToReflectedField 5715 * @param env A JREF index for the JNI environment object 5716 * @param clsJREF The JREF index of the class from which fieldID was 5717 * derived. 5718 * @param fieldID a jfieldID 5719 * @param isStatic argument that is not specified in Sun's JNI 1.2 spec, 5720 * but IS present in the 1.4.2 JDK's implementation! Our 5721 * implementation will just ignore it, in any case. This is a 5722 * good example of why the same entity 5723 * shouldn't get to write both the spec and the reference 5724 * implementation. 5725 * @return a JREF index for the java.lang.reflect.Field object associated 5726 * with fieldID. 5727 */ 5728 private static int ToReflectedField(JNIEnvironment env, int clsJREF, int fieldID, boolean isStatic) { 5729 if (traceJNI) VM.sysWrite("JNI called: ToReflectedField \n"); 5730 RuntimeEntrypoints.checkJNICountDownToGC(); 5731 5732 RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve(); 5733 return env.pushJNIRef(java.lang.reflect.JikesRVMSupport.createField(field)); 5734 } 5735 5736 /** Push a local frame for local references. 5737 * We could implement this more fancily, but it seems that we hardly need 5738 * to, since we allow an unlimited number of local refs. One could force 5739 * running out of memory in a long-running loop in JNI, of course. 5740 */ 5741 private static int PushLocalFrame(JNIEnvironment env, int capacity) { 5742 if (traceJNI) VM.sysWrite("JNI called: PushLocalFrame \n"); 5743 RuntimeEntrypoints.checkJNICountDownToGC(); 5744 5745 return 0; // OK 5746 } 5747 5748 /** Push a local frame for local references. 5749 * We could implement this more fancily, but it seems that we hardly need 5750 * to, since we allow an unlimited number of local refs. One could force 5751 * running out of memory in a long-running loop in JNI, of course, and this 5752 * might save us from that. Let's hold off until we need it. TODO. 5753 * 5754 * @return a local reference in the old frame that refers to the same object 5755 * as oldJREF. 5756 */ 5757 private static int PopLocalFrame(JNIEnvironment env, int resultJREF) { 5758 if (traceJNI) VM.sysWrite("JNI called: PopLocalFrame \n"); 5759 RuntimeEntrypoints.checkJNICountDownToGC(); 5760 5761 // do nothing. 5762 return resultJREF; 5763 } 5764 5765 /** 5766 * NewLocalRef 5767 * 5768 * @param env A JREF index for the JNI environment object 5769 * @param oldJREF JREF index of an existing reference. 5770 * @return a new local reference that refers to the same object as oldJREF. 5771 * C NULL pointer if the oldJREF refers to null. 5772 */ 5773 private static int NewLocalRef(JNIEnvironment env, int oldJREF) { 5774 if (traceJNI) VM.sysWrite("JNI called: NewLocalRef \n"); 5775 RuntimeEntrypoints.checkJNICountDownToGC(); 5776 5777 Object oldObj = env.getJNIRef(oldJREF); 5778 /* pushJNIRef automatically handles null refs properly. */ 5779 return env.pushJNIRef(oldObj); 5780 } 5781 5782 /** 5783 * EnsureLocalCapacity 5784 * 5785 * @param env A JREF index for the JNI environment object 5786 * @param capacity how many more local references do we want to ensure can 5787 * be created? 5788 * @return 0 on success. The JNI spec says that on failure this throws 5789 * OutOfMemoryError and returns a negative number. But we don't have to 5790 * worry about that at all. 5791 */ 5792 private static int EnsureLocalCapacity(JNIEnvironment env, int capacity) { 5793 if (traceJNI) VM.sysWrite("JNI called: EnsureLocalCapacity \n"); 5794 RuntimeEntrypoints.checkJNICountDownToGC(); 5795 5796 return 0; // success! 5797 } 5798 5799 /** GetStringRegion: Copy a region of Unicode characters from a string to 5800 * the given buffer. 5801 * 5802 * @param env A JREF index for the JNI environment object 5803 * @param strJREF a JREF index for the String object 5804 * @param start index to start reading characters from the string 5805 * @param len how many characters to read 5806 * @param buf the buffer to copy the region into 5807 * @exception StringIndexOutOfBoundsException if asked for an out-of-range 5808 * region of the string. 5809 */ 5810 private static void GetStringRegion(JNIEnvironment env, int strJREF, int start, int len, Address buf) { 5811 if (traceJNI) VM.sysWrite("JNI called: GetStringRegion \n"); 5812 RuntimeEntrypoints.checkJNICountDownToGC(); 5813 5814 try { 5815 String str = (String) env.getJNIRef(strJREF); 5816 char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str); 5817 int strOffset = java.lang.JikesRVMSupport.getStringOffset(str); 5818 int strLen = java.lang.JikesRVMSupport.getStringLength(str); 5819 if (strLen < start + len) { 5820 env.recordException(new StringIndexOutOfBoundsException()); 5821 return; 5822 } 5823 Address strBase = Magic.objectAsAddress(strChars); 5824 Address srcBase = strBase.plus(strOffset * 2).plus(start * 2); 5825 Memory.memcopy(buf, srcBase, len * 2); 5826 5827 } catch (Throwable unexpected) { 5828 if (traceJNI) unexpected.printStackTrace(System.err); 5829 env.recordException(unexpected); 5830 } 5831 } 5832 5833 /** GetStringUTFRegion: Copy a region of Unicode characters from a string to 5834 * the given buffer, as UTF8 characters. 5835 * 5836 * @param env A JREF index for the JNI environment object 5837 * @param strJREF a JREF index for the String object 5838 * @param start index to start reading characters from the string 5839 * @param len how many characters to read from the string 5840 * @param buf the buffer to copy the region into -- assume it's big enough 5841 * @exception StringIndexOutOfBoundsException if asked for an out-of-range 5842 * region of the string. 5843 */ 5844 private static void GetStringUTFRegion(JNIEnvironment env, int strJREF, int start, int len, Address buf) { 5845 if (traceJNI) VM.sysWrite("JNI called: GetStringUTFRegion \n"); 5846 RuntimeEntrypoints.checkJNICountDownToGC(); 5847 5848 try { 5849 String str = (String) env.getJNIRef(strJREF); 5850 String region = str.substring(start, start+len); 5851 // Get length of C string 5852 int utflen = UTF8Convert.utfLength(region) + 1; // for terminating zero 5853 JNIHelpers.createUTFForCFromString(region, buf, utflen); 5854 } catch (Throwable unexpected) { 5855 if (traceJNI) unexpected.printStackTrace(System.err); 5856 env.recordException(unexpected); 5857 } 5858 } 5859 5860 /** 5861 * GetPrimitiveArrayCritical: return a direct pointer to the primitive array 5862 * and disable GC so that the array will not be moved. This function 5863 * is intended to be paired with the ReleasePrimitiveArrayCritical function 5864 * within a short time so that GC will be reenabled 5865 * 5866 * @param env A JREF index for the JNI environment object 5867 * @param arrayJREF a JREF index for the primitive array in Java 5868 * @param isCopyAddress address of isCopy jboolean (an int) 5869 * @return The address of the primitive array, and the jboolean pointed to by isCopyAddress is set to false, indicating that this is not a copy. Address zero (null) on error. 5870 * @exception OutOfMemoryError is specified but will not be thrown in this implementation 5871 * since no copy will be made 5872 */ 5873 private static Address GetPrimitiveArrayCritical(JNIEnvironment env, int arrayJREF, Address isCopyAddress) { 5874 5875 if (traceJNI) VM.sysWrite("JNI called: GetPrimitiveArrayCritical \n"); 5876 RuntimeEntrypoints.checkJNICountDownToGC(); 5877 5878 try { 5879 Object primitiveArray = env.getJNIRef(arrayJREF); 5880 5881 // not an array, return null 5882 if (!primitiveArray.getClass().isArray()) { 5883 return Address.zero(); 5884 } 5885 5886 /* Set caller's isCopy boolean to false, if we got a valid (non-null) 5887 address */ 5888 JNIGenericHelpers.setBoolStar(isCopyAddress, false); 5889 5890 // For array of primitive, return the object address, which is the array itself 5891 VM.disableGC(true); 5892 return Magic.objectAsAddress(primitiveArray); 5893 } catch (Throwable unexpected) { 5894 if (traceJNI) unexpected.printStackTrace(System.err); 5895 env.recordException(unexpected); 5896 return Address.zero(); 5897 } 5898 } 5899 5900 /** 5901 * ReleasePrimitiveArrayCritical: this function is intended to be paired 5902 * with the GetPrimitiveArrayCritical function. 5903 * Since the native code has direct access 5904 * to the array, no copyback update is necessary; GC is simply reenabled. 5905 * @param env A JREF index for the JNI environment object 5906 * @param arrayJREF a JREF index for the primitive array in Java 5907 * @param arrayCopyAddress 5908 * @param mode a flag indicating whether to update the Java array with the 5909 * copy and whether to free the copy. For this implementation, 5910 * no copy was made so this flag has no effect. 5911 */ 5912 private static void ReleasePrimitiveArrayCritical(JNIEnvironment env, int arrayJREF, Address arrayCopyAddress, 5913 int mode) { 5914 if (traceJNI) VM.sysWrite("JNI called: ReleasePrimitiveArrayCritical \n"); 5915 RuntimeEntrypoints.checkJNICountDownToGC(); 5916 5917 try { 5918 VM.enableGC(true); 5919 } catch (Throwable unexpected) { 5920 if (traceJNI) unexpected.printStackTrace(System.err); 5921 env.recordException(unexpected); 5922 } 5923 } 5924 5925 /** GetStringCritical: 5926 * Like GetStringChars and ReleaseStringChars, but in some VM environments 5927 * the VM may be able to avoid making a copy. Native code must not issue 5928 * arbitrary JNI calls and must not cause the current thread to block. 5929 * 5930 * @param env A JREF index for the JNI environment object 5931 * @param strJREF a JREF index for the string in Java 5932 * @param isCopyAddress address of isCopy jboolean (an int) 5933 * @return The address of the backing array; address zero (null) on error, and the jboolean pointed to by isCopyAddress is set to false, indicating that this is not a copy. 5934 */ 5935 private static Address GetStringCritical(JNIEnvironment env, int strJREF, Address isCopyAddress) { 5936 if (traceJNI) VM.sysWrite("JNI called: GetStringCritical \n"); 5937 RuntimeEntrypoints.checkJNICountDownToGC(); 5938 5939 String str = (String) env.getJNIRef(strJREF); 5940 char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str); 5941 int strOffset = java.lang.JikesRVMSupport.getStringOffset(str); 5942 5943 /* Set caller's isCopy boolean to false, if we got a valid (non-null) 5944 address */ 5945 JNIGenericHelpers.setBoolStar(isCopyAddress, false); 5946 5947 VM.disableGC(true); 5948 Address strBase = Magic.objectAsAddress(strChars); 5949 return strBase.plus(strOffset * 2); 5950 } 5951 5952 /** 5953 * ReleaseStringCritical: this function is intended to be paired with the 5954 * GetStringCritical function. Since the native code has direct access 5955 * to the string's backing array of characters, no copyback update is 5956 * necessary; GC is simply reenabled. 5957 * 5958 * @param env A JREF index for the JNI environment object 5959 * @param strJREF a JREF index for the string in Java (ignored) 5960 * @param carray the pointer returned by GetStringCritical (ignored) 5961 */ 5962 private static void ReleaseStringCritical(JNIEnvironment env, int strJREF, Address carray) { 5963 if (traceJNI) VM.sysWrite("JNI called: ReleaseStringCritical \n"); 5964 RuntimeEntrypoints.checkJNICountDownToGC(); 5965 5966 try { 5967 VM.enableGC(true); 5968 } catch (Throwable unexpected) { 5969 if (traceJNI) unexpected.printStackTrace(System.err); 5970 env.recordException(unexpected); 5971 } 5972 } 5973 5974 private static int NewWeakGlobalRef(JNIEnvironment env, int objectJREF) { 5975 if (traceJNI) VM.sysWrite("JNI called: NewWeakGlobalRef \n"); 5976 RuntimeEntrypoints.checkJNICountDownToGC(); 5977 5978 try { 5979 Object obj1 = env.getJNIRef(objectJREF); 5980 return JNIGlobalRefTable.newWeakRef(obj1); 5981 } catch (Throwable unexpected) { 5982 if (traceJNI) unexpected.printStackTrace(System.err); 5983 env.recordException(unexpected); 5984 return 0; 5985 } 5986 } 5987 5988 private static void DeleteWeakGlobalRef(JNIEnvironment env, int refJREF) { 5989 if (traceJNI) VM.sysWrite("JNI called: DeleteWeakGlobalRef \n"); 5990 RuntimeEntrypoints.checkJNICountDownToGC(); 5991 5992 try { 5993 JNIGlobalRefTable.deleteWeakRef(refJREF); 5994 } catch (Throwable unexpected) { 5995 if (traceJNI) unexpected.printStackTrace(System.err); 5996 env.recordException(unexpected); 5997 } 5998 } 5999 6000 private static int ExceptionCheck(JNIEnvironment env) { 6001 if (traceJNI) VM.sysWrite("JNI called: ExceptionCheck \n"); 6002 RuntimeEntrypoints.checkJNICountDownToGC(); 6003 6004 return env.getException() == null ? 0 : 1; 6005 } 6006 6007 /******************************************************************* 6008 * These functions are in JNI 1.4 6009 */ 6010 6011 private static int NewDirectByteBuffer(JNIEnvironment env, Address address, long capacity) { 6012 if (traceJNI) VM.sysWrite("JNI called: NewDirectByteBuffer \n"); 6013 RuntimeEntrypoints.checkJNICountDownToGC(); 6014 6015 try { 6016 Buffer buffer = java.nio.JikesRVMSupport.newDirectByteBuffer(address, capacity); 6017 return env.pushJNIRef(buffer); 6018 } catch (Throwable unexpected) { 6019 if (traceJNI) unexpected.printStackTrace(System.err); 6020 env.recordException(unexpected); 6021 return 0; 6022 } 6023 } 6024 6025 private static Address GetDirectBufferAddress(JNIEnvironment env, int bufJREF) { 6026 if (traceJNI) VM.sysWrite("JNI called: GetDirectBufferAddress \n"); 6027 RuntimeEntrypoints.checkJNICountDownToGC(); 6028 6029 try { 6030 Buffer buffer = (Buffer) env.getJNIRef(bufJREF); 6031 //if (buffer instanceof ByteBuffer) { 6032 // VM.sysWrite("ByteBuffer, "); 6033 // if (((ByteBuffer)buffer).isDirect()) 6034 // VM.sysWrite("Direct, "); 6035 //} 6036 //VM.sysWriteln("Direct buffer address = ",result); 6037 return java.nio.JikesRVMSupport.getDirectBufferAddress(buffer); 6038 } catch (Throwable unexpected) { 6039 if (traceJNI) unexpected.printStackTrace(System.err); 6040 env.recordException(unexpected); 6041 return Address.zero(); 6042 } 6043 } 6044 6045 private static long GetDirectBufferCapacity(JNIEnvironment env, int bufJREF) { 6046 if (traceJNI) VM.sysWrite("JNI called: GetDirectBufferCapacity \n"); 6047 RuntimeEntrypoints.checkJNICountDownToGC(); 6048 6049 try { 6050 Buffer buffer = (Buffer) env.getJNIRef(bufJREF); 6051 return buffer.capacity(); 6052 } catch (Throwable unexpected) { 6053 if (traceJNI) unexpected.printStackTrace(System.err); 6054 env.recordException(unexpected); 6055 return -1; 6056 } 6057 } 6058 6059 /******************************************************************* 6060 * Empty Slots 6061 */ 6062 6063 private static int reserved0(JNIEnvironment env) { 6064 VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n"); 6065 VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP); 6066 return -1; 6067 } 6068 6069 private static int reserved1(JNIEnvironment env) { 6070 VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n"); 6071 VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP); 6072 return -1; 6073 } 6074 6075 private static int reserved2(JNIEnvironment env) { 6076 VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n"); 6077 VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP); 6078 return -1; 6079 } 6080 6081 private static int reserved3(JNIEnvironment env) { 6082 VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n"); 6083 VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP); 6084 return -1; 6085 } 6086 }