/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.jni; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.Buffer; import org.jikesrvm.ArchitectureSpecific.VM_JNIHelpers; import org.jikesrvm.VM; import org.jikesrvm.VM_Properties; import org.jikesrvm.VM_SizeConstants; import org.jikesrvm.classloader.VM_Array; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_Class; import org.jikesrvm.classloader.VM_ClassLoader; import org.jikesrvm.classloader.VM_Field; import org.jikesrvm.classloader.VM_MemberReference; import org.jikesrvm.classloader.VM_Method; import org.jikesrvm.classloader.VM_NativeMethod; import org.jikesrvm.classloader.VM_Type; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.classloader.VM_UTF8Convert; import org.jikesrvm.memorymanagers.mminterface.MM_Interface; import org.jikesrvm.objectmodel.VM_ObjectModel; import org.jikesrvm.runtime.VM_BootRecord; import org.jikesrvm.runtime.VM_Magic; import org.jikesrvm.runtime.VM_Memory; import org.jikesrvm.runtime.VM_Reflection; import org.jikesrvm.runtime.VM_Runtime; import org.jikesrvm.runtime.VM_SysCall; import static org.jikesrvm.runtime.VM_SysCall.sysCall; import org.vmmagic.pragma.NativeBridge; import org.vmmagic.unboxed.Address; import org.vmmagic.unboxed.AddressArray; import org.vmmagic.unboxed.Offset; import org.vmmagic.unboxed.Word; // TODO - Deal with subarch in JNI functions /** * This class implements the 232 JNI functions. * All methods here will be specially compiled with the necessary prolog to * perform the transition from native code (Linux/AIX/OSX convention) to RVM. * For this reason, no Java methods (including the JNI methods here) can call * any methods in this class from within Java. These JNI methods are to * be invoked from native C or C++. They're all declared private to enforce * this discipline. <br> * * The first argument for all the functions is the VM_JNIEnvironment object * of the thread. <br> * * The second argument is a JREF index for either the VM_Class object * or the object instance itself. To get the actual object, we use * the access method in VM_JNIEnvironment and cast the reference as * needed. <br> * * NOTE: * <ol> * <li> JREF index refers to the index into the side table of references * maintained by the VM_JNIEnvironment for each thread. Except for some cases * of array access, no references are passed directly to the native code; * rather, the references are kept in the table and the index is passed to the * native procedure. The JREF index are used by the JNI code to retrieve the * corresponding reference. </li> * * <li> Strings from C are seen as raw address (int) and need to be cloned as * Java Strings </li> * * <li> Because of many of the transformation above, the method signature of the * JNI functions may not match its definition in the jni.h file </li> * * <li> For exception handling, all JNI functions are wrapped in Try/Catch block * to catch all exception generated during JNI call, then these exceptions * or the appropriate exception to be thrown according to the spec is recorded * in VM_JNIEnvironment.pendingException. When the native code returns to the * the Java caller, the epilogue in the glue code will check for the pending * exception and deliver it to the caller as if executing an athrow bytecode * in the caller. </li> * </ol> * * Known Problems with our JNI implementation: * <ol> * <li>We can not return a global reference (whether weak * or strong) from a JNI function. We can only return local refs. * <li>We do not implement all of the invocation API; we don't support the * concept of a regular native program that links with "libjava" and * creates and destroys virtual machines. * <li>Similarly, we can not attach and detach a native threads to and from * the VM. * <li>We don't really free local refs when we call the * {@link #PopLocalFrame} method. * </ol> */ @SuppressWarnings({"unused", "UnusedDeclaration"}) // called from native code @NativeBridge public class VM_JNIFunctions implements VM_SizeConstants { // one message for each JNI function called from native public static final boolean traceJNI = VM_Properties.verboseJNI; // number of JNI function entries public static final int FUNCTIONCOUNT = 232; // JNI 1.4 /** * GetVersion: the version of the JNI * @param env A JREF index for the JNI environment object * @return 0x00010004 for JNI 1.4, 0x00010002 for JNI 1.2, * 0x00010001 for JNI 1.1, */ private static int GetVersion(VM_JNIEnvironment env) { if (traceJNI) VM.sysWrite("JNI called: GetVersion \n"); VM_Runtime.checkJNICountDownToGC(); return 0x00010004; // JNI 1.4 } /** * DefineClass: Loads a class from a buffer of raw class data. * @param env A JREF index for the JNI environment object * @param classNameAddress a raw address to a null-terminated string in C for the class name * @param classLoader a JREF index for the class loader assigned to the defined class * @param data buffer containing the <tt>.class</tt> file * @param dataLen buffer length * @return a JREF index for the Java Class object, or 0 if not found * @exception ClassFormatError if the class data does not specify a valid class * @exception ClassCircularityError (not implemented) * @exception OutOfMemoryError (not implemented) */ private static int DefineClass(VM_JNIEnvironment env, Address classNameAddress, int classLoader, Address data, int dataLen) { if (traceJNI) VM.sysWrite("JNI called: DefineClass \n"); VM_Runtime.checkJNICountDownToGC(); try { String classString = null; if (!classNameAddress.isZero()) { VM_JNIHelpers.createStringFromC(classNameAddress); } ClassLoader cl; if (classLoader == 0) { cl = VM_Class.getClassLoaderFromStackFrame(1); } else { cl = (ClassLoader) env.getJNIRef(classLoader); } byte[] bytecode = new byte[dataLen]; VM_Memory.memcopy(VM_Magic.objectAsAddress(bytecode), data, dataLen); final VM_Type vmType = VM_ClassLoader.defineClassInternal(classString, bytecode, 0, dataLen, cl); return env.pushJNIRef(vmType.getClassForType()); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * FindClass: given a class name, find its VM_Class, or 0 if not found * @param env A JREF index for the JNI environment object * @param classNameAddress a raw address to a null-terminated string in C for the class name * @return a JREF index for the Java Class object, or 0 if not found * @exception ClassFormatError (not implemented) * @exception ClassCircularityError (not implemented) * @exception NoClassDefFoundError if the class cannot be found * @exception OutOfMemoryError (not implemented) * @exception ExceptionInInitializerError (not implemented) */ private static int FindClass(VM_JNIEnvironment env, Address classNameAddress) { if (traceJNI) VM.sysWrite("JNI called: FindClass \n"); VM_Runtime.checkJNICountDownToGC(); String classString = null; try { classString = VM_JNIHelpers.createStringFromC(classNameAddress); if (traceJNI) VM.sysWriteln(classString); ClassLoader cl = VM_Class.getClassLoaderFromStackFrame(1); Class<?> matchedClass = Class.forName(classString.replace('/', '.'), true, cl); return env.pushJNIRef(matchedClass); } catch (ClassNotFoundException e) { if (traceJNI) e.printStackTrace(System.err); env.recordException(new NoClassDefFoundError(classString)); return 0; } catch (Throwable unexpected) { if (traceJNI) { if (VM.fullyBooted) { unexpected.printStackTrace(System.err); } else { VM.sysWrite("Unexpected exception ", unexpected.getClass().toString()); VM.sysWriteln(" to early in VM boot up to print ", unexpected.getMessage()); } } env.recordException(unexpected); return 0; } } /** * GetSuperclass: find the superclass given a class * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @return a JREF index for the super class object, or 0 if the given class * is java.lang.Object or an interface */ private static int GetSuperclass(VM_JNIEnvironment env, int classJREF) { if (traceJNI) VM.sysWrite("JNI called: GetSuperclass \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> cls = (Class<?>) env.getJNIRef(classJREF); Class<?> supercls = cls.getSuperclass(); return supercls == null ? 0 : env.pushJNIRef(supercls); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * IsAssignableFrom: determine if an an object of class or interface cls1 * can be cast to the class or interface cls2 * @param env A JREF index for the JNI environment object * @param firstClassJREF a JREF index for the first class object * @param secondClassJREF a JREF index for the second class object * @return true if cls1 can be assigned to cls2 */ private static boolean IsAssignableFrom(VM_JNIEnvironment env, int firstClassJREF, int secondClassJREF) { if (traceJNI) VM.sysWrite("JNI called: IsAssignableFrom \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> cls1 = (Class<?>) env.getJNIRef(firstClassJREF); Class<?> cls2 = (Class<?>) env.getJNIRef(secondClassJREF); return !(cls1 == null || cls2 == null) && cls2.isAssignableFrom(cls1); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * Throw: register a {@link Throwable} object as a pending exception, to be * delivered on return to the Java caller * @param env A JREF index for the JNI environment object * @param exceptionJREF A JREF index for the {@link Throwable} object to be * thrown * @return 0 if successful, -1 if not */ private static int Throw(VM_JNIEnvironment env, int exceptionJREF) { if (traceJNI) VM.sysWrite("JNI called: Throw \n"); VM_Runtime.checkJNICountDownToGC(); try { env.recordException((Throwable) env.getJNIRef(exceptionJREF)); return 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return -1; } } /** * ThrowNew * @param env A JREF index for the JNI environment object * @param throwableClassJREF a JREF index for the class object of the exception * @param exceptionNameAddress an address of the string in C * @return 0 if successful, -1 otherwise */ private static int ThrowNew(VM_JNIEnvironment env, int throwableClassJREF, Address exceptionNameAddress) { if (traceJNI) VM.sysWrite("JNI called: ThrowNew \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> cls = (Class<?>) env.getJNIRef(throwableClassJREF); // find the constructor that has a string as a parameter Class<?>[] argClasses = new Class[1]; argClasses[0] = VM_Type.JavaLangStringType.getClassForType(); Constructor<?> constMethod = cls.getConstructor(argClasses); // prepare the parameter list for reflective invocation Object[] argObjs = new Object[1]; argObjs[0] = VM_JNIHelpers.createStringFromC(exceptionNameAddress); // invoke the constructor to obtain a new Throwable object env.recordException((Throwable) constMethod.newInstance(argObjs)); return 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return -1; } } /** * ExceptionOccurred * @param env A JREF index for the JNI environment object * @return a JREF index for the pending exception or null if nothing pending */ private static int ExceptionOccurred(VM_JNIEnvironment env) { if (traceJNI) VM.sysWrite("JNI called: ExceptionOccurred \n"); VM_Runtime.checkJNICountDownToGC(); try { Throwable e = env.getException(); if (e == null) { return 0; } else { if (traceJNI) System.err.println(e.toString()); return env.pushJNIRef(e); } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return env.pushJNIRef(unexpected); } } /** * ExceptionDescribe: print the exception description and the stack trace back, * then clear the exception * @param env A JREF index for the JNI environment object */ private static void ExceptionDescribe(VM_JNIEnvironment env) { if (traceJNI) VM.sysWrite("JNI called: ExceptionDescribe \n"); VM_Runtime.checkJNICountDownToGC(); try { Throwable e = env.getException(); if (e != null) { env.recordException(null); e.printStackTrace(System.err); } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(null); // clear old exception and register new one env.recordException(unexpected); } } /** * ExceptionClear * @param env A JREF index for the JNI environment object */ private static void ExceptionClear(VM_JNIEnvironment env) { if (traceJNI) VM.sysWrite("JNI called: ExceptionClear \n"); VM_Runtime.checkJNICountDownToGC(); try { env.recordException(null); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(null); // clear old exception and register new one env.recordException(unexpected); } } /** * FatalError: print a message and terminate the VM * @param env A JREF index for the JNI environment object * @param messageAddress an address of the string in C */ private static void FatalError(VM_JNIEnvironment env, Address messageAddress) { if (traceJNI) VM.sysWrite("JNI called: FatalError \n"); VM_Runtime.checkJNICountDownToGC(); try { VM.sysWrite(VM_JNIHelpers.createStringFromC(messageAddress)); System.exit(VM.EXIT_STATUS_JNI_TROUBLE); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); System.exit(VM.EXIT_STATUS_RECURSIVELY_SHUTTING_DOWN); } } private static int NewGlobalRef(VM_JNIEnvironment env, int objectJREF) { if (traceJNI) VM.sysWrite("JNI called: NewGlobalRef\n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj1 = env.getJNIRef(objectJREF); return VM_JNIGlobalRefTable.newGlobalRef(obj1); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } private static void DeleteGlobalRef(VM_JNIEnvironment env, int refJREF) { if (traceJNI) VM.sysWrite("JNI called: DeleteGlobalRef\n"); VM_Runtime.checkJNICountDownToGC(); try { VM_JNIGlobalRefTable.deleteGlobalRef(refJREF); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } private static void DeleteLocalRef(VM_JNIEnvironment env, int objJREF) { if (traceJNI) VM.sysWrite("JNI called: DeleteLocalRef\n"); VM_Runtime.checkJNICountDownToGC(); try { env.deleteJNIRef(objJREF); } catch (ArrayIndexOutOfBoundsException e) { VM.sysFail("JNI refs array confused, or DeleteLocalRef gave us a bad JREF argument:", objJREF); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * IsSameObject: determine if two references point to the same object * @param env A JREF index for the JNI environment object * @param obj1JREF A JREF index for the first object * @param obj2JREF A JREF index for the second object * @return <code>true</code> if it's the same object, false otherwise */ private static boolean IsSameObject(VM_JNIEnvironment env, int obj1JREF, int obj2JREF) { if (traceJNI) VM.sysWrite("JNI called: IsSameObject \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj1 = env.getJNIRef(obj1JREF); Object obj2 = env.getJNIRef(obj2JREF); return obj1 == obj2; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(null); // clear old exception and register new one env.recordException(unexpected); return false; } } /** * AllocObject: allocate the space for an object without running any constructor * the header is filled and the fields are initialized to null * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @return a JREF index for the uninitialized object * @exception InstantiationException if the class is abstract or is an interface * @exception OutOfMemoryError if no more memory to allocate */ private static int AllocObject(VM_JNIEnvironment env, int classJREF) throws InstantiationException, OutOfMemoryError { if (traceJNI) VM.sysWrite("JNI called: AllocObject \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> javaCls = (Class<?>) env.getJNIRef(classJREF); VM_Type type = java.lang.JikesRVMSupport.getTypeForClass(javaCls); if (type.isArrayType() || type.isPrimitiveType()) { env.recordException(new InstantiationException()); return 0; } VM_Class cls = type.asClass(); if (cls.isAbstract() || cls.isInterface()) { env.recordException(new InstantiationException()); return 0; } Object newObj = VM_Runtime.resolvedNewScalar(cls); return env.pushJNIRef(newObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewObject: create a new object instance * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @return the new object instance * @exception InstantiationException if the class is abstract or is an interface * @exception OutOfMemoryError if no more memory to allocate */ private static int NewObject(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: NewObject \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> cls = (Class<?>) env.getJNIRef(classJREF); VM_Class vmcls = java.lang.JikesRVMSupport.getTypeForClass(cls).asClass(); if (vmcls.isAbstract() || vmcls.isInterface()) { env.recordException(new InstantiationException()); return 0; } Object newobj = VM_JNIHelpers.invokeInitializer(cls, methodID, Address.zero(), false, true); return env.pushJNIRef(newobj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewObjectV: create a new object instance * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or * 2-words of the appropriate type for the constructor invocation * @return the new object instance * @exception InstantiationException if the class is abstract or is an interface * @exception OutOfMemoryError if no more memory to allocate */ private static int NewObjectV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: NewObjectV \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> cls = (Class<?>) env.getJNIRef(classJREF); VM_Class vmcls = java.lang.JikesRVMSupport.getTypeForClass(cls).asClass(); if (vmcls.isAbstract() || vmcls.isInterface()) { env.recordException(new InstantiationException()); return 0; } Object newobj = VM_JNIHelpers.invokeInitializer(cls, methodID, argAddress, false, false); return env.pushJNIRef(newobj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewObjectA: create a new object instance * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and * hold an argument of the appropriate type for the constructor invocation * @exception InstantiationException if the class is abstract or is an interface * @exception OutOfMemoryError if no more memory to allocate * @return the new object instance */ private static int NewObjectA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: NewObjectA \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> cls = (Class<?>) env.getJNIRef(classJREF); VM_Class vmcls = java.lang.JikesRVMSupport.getTypeForClass(cls).asClass(); if (vmcls.isAbstract() || vmcls.isInterface()) { env.recordException(new InstantiationException()); return 0; } Object newobj = VM_JNIHelpers.invokeInitializer(cls, methodID, argAddress, true, false); return env.pushJNIRef(newobj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetObjectClass * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object to check * @return a JREF index for the Class object */ private static int GetObjectClass(VM_JNIEnvironment env, int objJREF) { if (traceJNI) VM.sysWrite("JNI called: GetObjectClass \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); return env.pushJNIRef(obj.getClass()); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * IsInstanceOf: determine if an object is an instance of the class * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object to check * @param classJREF a JREF index for the class to check * @return true if the object is an instance of the class */ private static int IsInstanceOf(VM_JNIEnvironment env, int objJREF, int classJREF) { if (traceJNI) VM.sysWrite("JNI called: IsInstanceOf \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> cls = (Class<?>) env.getJNIRef(classJREF); Object obj = env.getJNIRef(objJREF); if (obj == null) return 0; // null instanceof T is always false VM_Type RHStype = VM_ObjectModel.getObjectType(obj); VM_Type LHStype = java.lang.JikesRVMSupport.getTypeForClass(cls); return (LHStype == RHStype || VM_Runtime.isAssignableWith(LHStype, RHStype)) ? 1 : 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetMethodID: get the virtual method ID given the name and the signature * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodNameAddress a raw address to a null-terminated string in C for the method name * @param methodSigAddress a raw address to a null-terminated string in C for the method signature * @return id of a VM_MethodReference * @exception NoSuchMethodError if the method cannot be found * @exception ExceptionInInitializerError if the class or interface static initializer fails * @exception OutOfMemoryError if the system runs out of memory */ private static int GetMethodID(VM_JNIEnvironment env, int classJREF, Address methodNameAddress, Address methodSigAddress) { if (traceJNI) VM.sysWrite("JNI called: GetMethodID \n"); VM_Runtime.checkJNICountDownToGC(); try { // obtain the names as String from the native space String methodString = VM_JNIHelpers.createStringFromC(methodNameAddress); VM_Atom methodName = VM_Atom.findOrCreateAsciiAtom(methodString); String sigString = VM_JNIHelpers.createStringFromC(methodSigAddress); VM_Atom sigName = VM_Atom.findOrCreateAsciiAtom(sigString); // get the target class Class<?> jcls = (Class<?>) env.getJNIRef(classJREF); VM_Type type = java.lang.JikesRVMSupport.getTypeForClass(jcls); if (!type.isClassType()) { env.recordException(new NoSuchMethodError()); return 0; } VM_Class klass = type.asClass(); if (!klass.isInitialized(false)) { VM_Runtime.initializeClassForDynamicLink(klass); } // Find the target method final VM_Method meth; if (methodString.equals("<init>")) { meth = klass.findInitializerMethod(sigName); } else { meth = klass.findVirtualMethod(methodName, sigName); } if (meth == null) { env.recordException(new NoSuchMethodError(klass + ": " + methodName + " " + sigName)); return 0; } if (traceJNI) VM.sysWrite("got method " + meth + "\n"); return meth.getId(); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallObjectMethod: invoke a virtual method that returns an object * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @return the JREF index for the object returned from the method invocation */ private static int CallObjectMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallObjectMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, null, false); return env.pushJNIRef(returnObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallObjectMethodV: invoke a virtual method that returns an object * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the JREF index for the object returned from the method invocation */ private static int CallObjectMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallObjectMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, null, false); return env.pushJNIRef(returnObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallObjectMethodA: invoke a virtual method that returns an object value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the JREF index for the object returned from the method invocation */ private static int CallObjectMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallObjectMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, null, false); return env.pushJNIRef(returnObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallBooleanMethod: invoke a virtual method that returns a boolean value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @return the boolean value returned from the method invocation */ private static boolean CallBooleanMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallBooleanMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Boolean, false); return VM_Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * CallBooleanMethodV: invoke a virtual method that returns a boolean value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the boolean value returned from the method invocation */ private static boolean CallBooleanMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallBooleanMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Boolean, false); return VM_Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * CallBooleanMethodA: invoke a virtual method that returns a boolean value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the boolean value returned from the method invocation */ private static boolean CallBooleanMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallBooleanMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Boolean, false); return VM_Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * CallByteMethod: invoke a virtual method that returns a byte value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @return the byte value returned from the method invocation */ private static byte CallByteMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallByteMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Byte, false); return VM_Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallByteMethodV: invoke a virtual method that returns a byte value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the byte value returned from the method invocation */ private static byte CallByteMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallByteMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Byte, false); return VM_Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallByteMethodA: invoke a virtual method that returns a byte value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the byte value returned from the method invocation */ private static byte CallByteMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallByteMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Byte, false); return VM_Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallCharMethod: invoke a virtual method that returns a char value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @return the char value returned from the method invocation */ private static char CallCharMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallCharMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Char, false); return VM_Reflection.unwrapChar(returnObj); // should be a wrapper for a char value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallCharMethodV: invoke a virtual method that returns a char value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the char value returned from the method invocation */ private static char CallCharMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallCharMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Char, false); return VM_Reflection.unwrapChar(returnObj); // should be a wrapper for a char value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallCharMethodA: invoke a virtual method that returns a char value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the char value returned from the method invocation */ private static char CallCharMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallCharMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Char, false); return VM_Reflection.unwrapChar(returnObj); // should be a wrapper for a char value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallShortMethod: invoke a virtual method that returns a short value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @return the short value returned from the method invocation */ private static short CallShortMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallShortMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Short, false); return VM_Reflection.unwrapShort(returnObj); // should be a wrapper for a short value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallShortMethodV: invoke a virtual method that returns a short value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the short value returned from the method invocation */ private static short CallShortMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallShortMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Short, false); return VM_Reflection.unwrapShort(returnObj); // should be a wrapper for a short value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallShortMethodA: invoke a virtual method that returns a short value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the short value returned from the method invocation */ private static short CallShortMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallShortMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Short, false); return VM_Reflection.unwrapShort(returnObj); // should be a wrapper for a short value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallIntMethod: invoke a virtual method that returns a int value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @return the int value returned from the method invocation */ private static int CallIntMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallIntMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Int, false); return VM_Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallIntMethodV: invoke a virtual method that returns an int value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the int value returned from the method invocation */ private static int CallIntMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallIntMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Int, false); return VM_Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallIntMethodA: invoke a virtual method that returns an integer value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the integer value returned from the method invocation */ private static int CallIntMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallIntMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Int, false); return VM_Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallLongMethod: invoke a virtual method that returns a long value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @return the long value returned from the method invocation */ private static long CallLongMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallLongMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Long, false); return VM_Reflection.unwrapLong(returnObj); // should be a wrapper for a long value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallLongMethodV: invoke a virtual method that returns a long value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the long value returned from the method invocation */ private static long CallLongMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallLongMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Long, false); return VM_Reflection.unwrapLong(returnObj); // should be a wrapper for a long value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallLongMethodA: invoke a virtual method that returns a long value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the long value returned from the method invocation */ private static long CallLongMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallLongMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Long, false); return VM_Reflection.unwrapLong(returnObj); // should be a wrapper for a long value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallFloatMethod: invoke a virtual method that returns a float value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @return the float value returned from the method invocation */ private static float CallFloatMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallFloatMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Float, false); return VM_Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallFloatMethodV: invoke a virtual method that returns a float value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the float value returned from the method invocation */ private static float CallFloatMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallFloatMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Float, false); return VM_Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallFloatMethodA: invoke a virtual method that returns a float value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the float value returned from the method invocation */ private static float CallFloatMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallFloatMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Float, false); return VM_Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallDoubleMethod: invoke a virtual method that returns a double value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @return the double value returned from the method invocation */ private static double CallDoubleMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallDoubleMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Double, false); return VM_Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallDoubleMethodV: invoke a virtual method that returns a double value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the double value returned from the method invocation */ private static double CallDoubleMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallDoubleMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Double, false); return VM_Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallDoubleMethodA: invoke a virtual method that returns a double value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the double value returned from the method invocation */ private static double CallDoubleMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallDoubleMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Double, false); return VM_Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallVoidMethod: invoke a virtual method that returns a void value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference */ private static void CallVoidMethod(VM_JNIEnvironment env, int objJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallVoidMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Void, false); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * CallVoidMethodV: invoke a virtual method that returns void * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation */ private static void CallVoidMethodV(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallVoidMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Void, false); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * CallVoidMethodA: invoke a virtual method that returns void * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation */ private static void CallVoidMethodA(VM_JNIEnvironment env, int objJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallVoidMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Void, false); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * CallNonvirtualObjectMethod: invoke a virtual method that returns an object * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @return the JREF index for the object returned from the method invocation */ private static int CallNonvirtualObjectMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualObjectMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, null, true); return env.pushJNIRef(returnObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualObjectMethodV: invoke a virtual method that returns an object * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the JREF index for the object returned from the method invocation */ private static int CallNonvirtualObjectMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualObjectMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, null, true); return env.pushJNIRef(returnObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualNonvirtualObjectMethodA: invoke a virtual method that returns an object value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the JREF index for the object returned from the method invocation */ private static int CallNonvirtualObjectMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualObjectMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, null, true); return env.pushJNIRef(returnObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualBooleanMethod: invoke a virtual method that returns a boolean value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @return the boolean value returned from the method invocation */ private static boolean CallNonvirtualBooleanMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualBooleanMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Boolean, true); return VM_Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * CallNonvirtualBooleanMethodV: invoke a virtual method that returns a boolean value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the boolean value returned from the method invocation */ private static boolean CallNonvirtualBooleanMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualBooleanMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Boolean, true); return VM_Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * CallNonvirtualBooleanMethodA: invoke a virtual method that returns a boolean value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the boolean value returned from the method invocation */ private static boolean CallNonvirtualBooleanMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualBooleanMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Boolean, true); return VM_Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * CallNonvirtualByteMethod: invoke a virtual method that returns a byte value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @return the byte value returned from the method invocation */ private static byte CallNonvirtualByteMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualByteMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Byte, true); return VM_Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualByteMethodV: invoke a virtual method that returns a byte value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param classJREF a JREF index for the class object that declares this method * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the byte value returned from the method invocation */ private static byte CallNonvirtualByteMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualByteMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Byte, true); return VM_Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualByteMethodA: invoke a virtual method that returns a byte value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param methodID id of a VM_MethodReference * @param classJREF a JREF index for the class object that declares this method * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the byte value returned from the method invocation */ private static byte CallNonvirtualByteMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualByteMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Byte, true); return VM_Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualCharMethod: invoke a virtual method that returns a char value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @return the char value returned from the method invocation */ private static char CallNonvirtualCharMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualCharMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Char, true); return VM_Reflection.unwrapChar(returnObj); // should be a wrapper for a char value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualCharMethodV: invoke a virtual method that returns a char value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the char value returned from the method invocation */ private static char CallNonvirtualCharMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualCharMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Char, true); return VM_Reflection.unwrapChar(returnObj); // should be a wrapper for a char value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualCharMethodA: invoke a virtual method that returns a char value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the char value returned from the method invocation */ private static char CallNonvirtualCharMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualCharMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Char, true); return VM_Reflection.unwrapChar(returnObj); // should be a wrapper for a char value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualShortMethod: invoke a virtual method that returns a short value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @return the short value returned from the method invocation */ private static short CallNonvirtualShortMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualShortMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Short, true); return VM_Reflection.unwrapShort(returnObj); // should be a wrapper for a short value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualShortMethodV: invoke a virtual method that returns a short value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the short value returned from the method invocation */ private static short CallNonvirtualShortMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualShortMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Short, true); return VM_Reflection.unwrapShort(returnObj); // should be a wrapper for a short value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualShortMethodA: invoke a virtual method that returns a short value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the short value returned from the method invocation */ private static short CallNonvirtualShortMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualShortMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Short, true); return VM_Reflection.unwrapShort(returnObj); // should be a wrapper for a short value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualIntMethod: invoke a virtual method that returns a int value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @return the int value returned from the method invocation */ private static int CallNonvirtualIntMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualIntMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Int, true); return VM_Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualIntMethodV: invoke a virtual method that returns an int value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the int value returned from the method invocation */ private static int CallNonvirtualIntMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualIntMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Int, true); return VM_Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualIntMethodA: invoke a virtual method that returns an integer value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the integer value returned from the method invocation */ private static int CallNonvirtualIntMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualIntMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Int, true); return VM_Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualLongMethod: invoke a virtual method that returns a long value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @return the long value returned from the method invocation */ private static long CallNonvirtualLongMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualLongMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Long, true); return VM_Reflection.unwrapLong(returnObj); // should be a wrapper for a long value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualLongMethodV: invoke a virtual method that returns a long value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the long value returned from the method invocation */ private static long CallNonvirtualLongMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualLongMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Long, true); return VM_Reflection.unwrapLong(returnObj); // should be a wrapper for a long value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualLongMethodA: invoke a virtual method that returns a long value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the long value returned from the method invocation */ private static long CallNonvirtualLongMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualLongMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Long, true); return VM_Reflection.unwrapLong(returnObj); // should be a wrapper for a long value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualFloatMethod: invoke a virtual method that returns a float value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @return the float value returned from the method invocation */ private static float CallNonvirtualFloatMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualFloatMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Float, true); return VM_Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualFloatMethodV: invoke a virtual method that returns a float value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the float value returned from the method invocation */ private static float CallNonvirtualFloatMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualFloatMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Float, true); return VM_Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualFloatMethodA: invoke a virtual method that returns a float value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the float value returned from the method invocation */ private static float CallNonvirtualFloatMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualFloatMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Float, true); return VM_Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualDoubleMethod: invoke a virtual method that returns a double value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @return the double value returned from the method invocation */ private static double CallNonvirtualDoubleMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualDoubleMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Double, true); return VM_Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualDoubleMethodV: invoke a virtual method that returns a double value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation * @return the double value returned from the method invocation */ private static double CallNonvirtualDoubleMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualDoubleMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Double, true); return VM_Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualDoubleMethodA: invoke a virtual method that returns a double value * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation * @return the double value returned from the method invocation */ private static double CallNonvirtualDoubleMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualDoubleMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object returnObj = VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Double, true); return VM_Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallNonvirtualVoidMethod: invoke a virtual method that returns a void value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; * they are saved in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference */ private static void CallNonvirtualVoidMethod(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualVoidMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_JNIHelpers.invokeWithDotDotVarArg(obj, methodID, VM_TypeReference.Void, true); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * CallNonvirtualVoidMethodV: invoke a virtual method that returns void * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is * 1-word or 2-words of the appropriate type for the method invocation */ private static void CallNonvirtualVoidMethodV(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualVoidMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, VM_TypeReference.Void, true); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * CallNonvirtualVoidMethodA: invoke a virtual method that returns void * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object instance * @param classJREF a JREF index for the class object that declares this method * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word * and hold an argument of the appropriate type for the method invocation */ private static void CallNonvirtualVoidMethodA(VM_JNIEnvironment env, int objJREF, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualVoidMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_JNIHelpers.invokeWithJValue(obj, methodID, argAddress, VM_TypeReference.Void, true); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetFieldID: return a field id, which can be cached in native code and reused * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldNameAddress a raw address to a null-terminated string in C for the field name * @param descriptorAddress a raw address to a null-terminated string in C for the descriptor * @return the fieldID of an instance field given the class, field name * and type. Return 0 if the field is not found * @exception NoSuchFieldError if the specified field cannot be found * @exception ExceptionInInitializerError if the class initializer fails * @exception OutOfMemoryError if the system runs out of memory */ private static int GetFieldID(VM_JNIEnvironment env, int classJREF, Address fieldNameAddress, Address descriptorAddress) { if (traceJNI) VM.sysWrite("JNI called: GetFieldID \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> cls = (Class<?>) env.getJNIRef(classJREF); String fieldString = VM_JNIHelpers.createStringFromC(fieldNameAddress); VM_Atom fieldName = VM_Atom.findOrCreateAsciiAtom(fieldString); String descriptorString = VM_JNIHelpers.createStringFromC(descriptorAddress); VM_Atom descriptor = VM_Atom.findOrCreateAsciiAtom(descriptorString); // list of all instance fields including superclasses VM_Field[] fields = java.lang.JikesRVMSupport.getTypeForClass(cls).getInstanceFields(); for (VM_Field f : fields) { if (f.getName() == fieldName && f.getDescriptor() == descriptor) { return f.getId(); } } // create exception and return 0 if not found env.recordException(new NoSuchFieldError(fieldString + ", " + descriptorString + " of " + cls)); return 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetObjectField: read a instance field of type Object * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @return the value of the Object field, converted to a JREF index * or 0 if the fieldID is incorrect */ private static int GetObjectField(VM_JNIEnvironment env, int objJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetObjectField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); Object objVal = field.getObjectUnchecked(obj); return env.pushJNIRef(objVal); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetBooleanField: read an instance field of type boolean * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @return the value of the boolean field, or 0 if the fieldID is incorrect */ private static int GetBooleanField(VM_JNIEnvironment env, int objJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetBooleanField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getBooleanValueUnchecked(obj) ? 1 : 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetByteField: read an instance field of type byte * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @return the value of the byte field, or 0 if the fieldID is incorrect */ private static int GetByteField(VM_JNIEnvironment env, int objJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetByteField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getByteValueUnchecked(obj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetCharField: read an instance field of type character * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @return the value of the character field, or 0 if the fieldID is incorrect */ private static int GetCharField(VM_JNIEnvironment env, int objJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetCharField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getCharValueUnchecked(obj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetShortField: read an instance field of type short * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @return the value of the short field, or 0 if the fieldID is incorrect */ private static int GetShortField(VM_JNIEnvironment env, int objJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetShortField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getShortValueUnchecked(obj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetIntField: read an instance field of type integer * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @return the value of the integer field, or 0 if the fieldID is incorrect */ private static int GetIntField(VM_JNIEnvironment env, int objJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetIntField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getIntValueUnchecked(obj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetLongField: read an instance field of type long * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @return the value of the long field or 0 if the fieldID is incorrect */ private static long GetLongField(VM_JNIEnvironment env, int objJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetLongField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getLongValueUnchecked(obj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0L; } } /** * GetFloatField: read an instance field of type float * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @return the value of the float field or 0 if the fieldID is incorrect */ private static float GetFloatField(VM_JNIEnvironment env, int objJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetFloatField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getFloatValueUnchecked(obj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0f; } } /** * GetDoubleField: read an instance field of type double * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @return the value of the double field or 0 if the fieldID is incorrect */ private static double GetDoubleField(VM_JNIEnvironment env, int objJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetDoubleField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getDoubleValueUnchecked(obj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0.0; } } /** * SetObjectField: set a instance field of type Object * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @param valueJREF a JREF index for the value to assign */ private static void SetObjectField(VM_JNIEnvironment env, int objJREF, int fieldID, int valueJREF) { if (traceJNI) VM.sysWrite("JNI called: SetObjectField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); Object value = env.getJNIRef(valueJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setObjectValueUnchecked(obj, value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetBooleanField: set an instance field of type boolean * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @param value boolean value to assign */ private static void SetBooleanField(VM_JNIEnvironment env, int objJREF, int fieldID, boolean value) { if (traceJNI) VM.sysWrite("JNI called: SetBooleanField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setBooleanValueUnchecked(obj, value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetByteField: set an instance field of type byte * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @param value byte value to assign */ private static void SetByteField(VM_JNIEnvironment env, int objJREF, int fieldID, byte value) { if (traceJNI) VM.sysWrite("JNI called: SetByteField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setByteValueUnchecked(obj, value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetCharField: set an instance field of type char * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @param value char value to assign */ private static void SetCharField(VM_JNIEnvironment env, int objJREF, int fieldID, char value) { if (traceJNI) VM.sysWrite("JNI called: SetCharField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setCharValueUnchecked(obj, value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetShortField: set an instance field of type short * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @param value short value to assign */ private static void SetShortField(VM_JNIEnvironment env, int objJREF, int fieldID, short value) { if (traceJNI) VM.sysWrite("JNI called: SetShortField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setShortValueUnchecked(obj, value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetIntField: set an instance field of type integer * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @param value integer value to assign */ private static void SetIntField(VM_JNIEnvironment env, int objJREF, int fieldID, int value) { if (traceJNI) VM.sysWrite("JNI called: SetIntField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setIntValueUnchecked(obj, value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetLongField: set an instance field of type long * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @param value long value to assign */ private static void SetLongField(VM_JNIEnvironment env, int objJREF, int fieldID, long value) { if (traceJNI) VM.sysWrite("JNI called: SetLongField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setLongValueUnchecked(obj, value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetFloatField: set an instance field of type float * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @param value float value to assign */ private static void SetFloatField(VM_JNIEnvironment env, int objJREF, int fieldID, float value) { if (traceJNI) VM.sysWrite("JNI called: SetFloatField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setFloatValueUnchecked(obj, value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetDoubleField: set an instance field of type double * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the target object * @param fieldID the id for the VM_Field that describes this field * @param value double value to assign */ private static void SetDoubleField(VM_JNIEnvironment env, int objJREF, int fieldID, double value) { if (traceJNI) VM.sysWrite("JNI called: SetDoubleField \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setDoubleValueUnchecked(obj, value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetStaticMethodID: return the method ID for invocation later * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodNameAddress a raw address to a null-terminated string in C for the method name * @param methodSigAddress a raw address to a null-terminated string in C for <DOCUMENTME TODO> * @return a method ID or null if it fails * @exception NoSuchMethodError if the method is not found * @exception ExceptionInInitializerError if the initializer fails * @exception OutOfMemoryError if the system runs out of memory */ private static int GetStaticMethodID(VM_JNIEnvironment env, int classJREF, Address methodNameAddress, Address methodSigAddress) { if (traceJNI) VM.sysWrite("JNI called: GetStaticMethodID \n"); VM_Runtime.checkJNICountDownToGC(); try { // obtain the names as String from the native space String methodString = VM_JNIHelpers.createStringFromC(methodNameAddress); VM_Atom methodName = VM_Atom.findOrCreateAsciiAtom(methodString); String sigString = VM_JNIHelpers.createStringFromC(methodSigAddress); VM_Atom sigName = VM_Atom.findOrCreateAsciiAtom(sigString); // get the target class Class<?> jcls = (Class<?>) env.getJNIRef(classJREF); VM_Type type = java.lang.JikesRVMSupport.getTypeForClass(jcls); if (!type.isClassType()) { env.recordException(new NoSuchMethodError()); return 0; } VM_Class klass = type.asClass(); if (!klass.isInitialized(false)) { VM_Runtime.initializeClassForDynamicLink(klass); } // Find the target method VM_Method meth = klass.findStaticMethod(methodName, sigName); if (meth == null) { env.recordException(new NoSuchMethodError()); return 0; } if (traceJNI) VM.sysWrite("got method " + meth + "\n"); return meth.getId(); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticObjectMethod: invoke a static method that returns an object value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @return the JREF index for the object returned from the method invocation */ private static int CallStaticObjectMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticObjectMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(methodID, null); return env.pushJNIRef(returnObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticObjectMethodV: invoke a static method that returns an object * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words * of the appropriate type for the method invocation * @return the JREF index for the object returned from the method invocation */ private static int CallStaticObjectMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticObjectMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, null); return env.pushJNIRef(returnObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticObjectMethodA: invoke a static method that returns an object * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation * @return the JREF index for the object returned from the method invocation */ private static int CallStaticObjectMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticObjectMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithJValue(methodID, argAddress, null); return env.pushJNIRef(returnObj); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticBooleanMethod: invoke a static method that returns a boolean value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @return the boolean value returned from the method invocation */ private static boolean CallStaticBooleanMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticBooleanMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(methodID, VM_TypeReference.Boolean); return VM_Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * CallStaticBooleanMethodV: invoke a static method that returns a boolean value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words * of the appropriate type for the method invocation * @return the boolean value returned from the method invocation */ private static boolean CallStaticBooleanMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticBooleanMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, VM_TypeReference.Boolean); return VM_Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * CallStaticBooleanMethodA: invoke a static method that returns a boolean value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation * @return the boolean value returned from the method invocation */ private static boolean CallStaticBooleanMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticBooleanMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithJValue(methodID, argAddress, VM_TypeReference.Boolean); return VM_Reflection.unwrapBoolean(returnObj); // should be a wrapper for a boolean value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return false; } } /** * CallStaticByteMethod: invoke a static method that returns a byte value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @return the byte value returned from the method invocation */ private static byte CallStaticByteMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticByteMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(methodID, VM_TypeReference.Byte); return VM_Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticByteMethodV: invoke a static method that returns a byte value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words * of the appropriate type for the method invocation * @return the byte value returned from the method invocation */ private static byte CallStaticByteMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticByteMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, VM_TypeReference.Byte); return VM_Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticByteMethodA: invoke a static method that returns a byte value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation * @return the byte value returned from the method invocation */ private static byte CallStaticByteMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticByteMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithJValue(methodID, argAddress, VM_TypeReference.Byte); return VM_Reflection.unwrapByte(returnObj); // should be a wrapper for a byte value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticCharMethod: invoke a static method that returns a char value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @return the char value returned from the method invocation */ private static char CallStaticCharMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticCharMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(methodID, VM_TypeReference.Char); return VM_Reflection.unwrapChar(returnObj); // should be a wrapper for a char value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticCharMethodV: invoke a static method that returns a char value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words * of the appropriate type for the method invocation * @return the char value returned from the method invocation */ private static char CallStaticCharMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticCharMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, VM_TypeReference.Char); return VM_Reflection.unwrapChar(returnObj); // should be a wrapper for a char value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticCharMethodA: invoke a static method that returns a char value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation * @return the char value returned from the method invocation */ private static char CallStaticCharMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticCharMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithJValue(methodID, argAddress, VM_TypeReference.Char); return VM_Reflection.unwrapChar(returnObj); // should be a wrapper for a char value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticShortMethod: invoke a static method that returns a short value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @return the short value returned from the method invocation */ private static short CallStaticShortMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticShortMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(methodID, VM_TypeReference.Short); return VM_Reflection.unwrapShort(returnObj); // should be a wrapper for an short value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticShortMethodV: invoke a static method that returns a short value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words * of the appropriate type for the method invocation * @return the short value returned from the method invocation */ private static short CallStaticShortMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticShortMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, VM_TypeReference.Short); return VM_Reflection.unwrapShort(returnObj); // should be a wrapper for a short value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticShortMethodA: invoke a static method that returns a short value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation * @return the short value returned from the method invocation */ private static short CallStaticShortMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticShortMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithJValue(methodID, argAddress, VM_TypeReference.Short); return VM_Reflection.unwrapShort(returnObj); // should be a wrapper for a short value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticIntMethod: invoke a static method that returns an integer value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @return the integer value returned from the method invocation */ private static int CallStaticIntMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticIntMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(methodID, VM_TypeReference.Int); return VM_Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticIntMethodV: invoke a static method that returns an integer value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words * of the appropriate type for the method invocation * @return the integer value returned from the method invocation */ private static int CallStaticIntMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticIntMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, VM_TypeReference.Int); return VM_Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticIntMethodA: invoke a static method that returns an integer value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation * @return the integer value returned from the method invocation */ private static int CallStaticIntMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticIntMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithJValue(methodID, argAddress, VM_TypeReference.Int); return VM_Reflection.unwrapInt(returnObj); // should be a wrapper for an integer value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticLongMethod: invoke a static method that returns a long value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @return the long value returned from the method invocation */ private static long CallStaticLongMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticLongMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(methodID, VM_TypeReference.Long); return VM_Reflection.unwrapLong(returnObj); // should be a wrapper for a long value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0L; } } /** * CallStaticLongMethodV: invoke a static method that returns a long value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words * of the appropriate type for the method invocation * @return the long value returned from the method invocation */ private static long CallStaticLongMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticLongMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, VM_TypeReference.Long); return VM_Reflection.unwrapLong(returnObj); // should be a wrapper for a long value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0L; } } /** * CallStaticLongMethodA: invoke a static method that returns a long value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation * @return the long value returned from the method invocation */ private static long CallStaticLongMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticLongMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithJValue(methodID, argAddress, VM_TypeReference.Long); return VM_Reflection.unwrapLong(returnObj); // should be a wrapper for a long value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0L; } } /** * CallStaticFloagMethod: invoke a static method that returns a float value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @return the float value returned from the method invocation */ private static float CallStaticFloatMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticFloatMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(methodID, VM_TypeReference.Float); return VM_Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0f; } } /** * CallStaticFloatMethodV: invoke a static method that returns a float value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words * of the appropriate type for the method invocation * @return the float value returned from the method invocation */ private static float CallStaticFloatMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticFloatMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, VM_TypeReference.Float); return VM_Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0f; } } /** * CallStaticFloatMethodA: invoke a static method that returns a float value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation * @return the float value returned from the method invocation */ private static float CallStaticFloatMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticFloatMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithJValue(methodID, argAddress, VM_TypeReference.Float); return VM_Reflection.unwrapFloat(returnObj); // should be a wrapper for a float value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0f; } } /** * CallStaticDoubleMethod: invoke a static method that returns a double value * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID an id of a VM_MethodReference * @return the double value returned from the method invocation */ private static double CallStaticDoubleMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticDoubleMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithDotDotVarArg(methodID, VM_TypeReference.Double); return VM_Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticDoubleMethodV: invoke a static method that returns a double value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID an id of a VM_MethodReference * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words * of the appropriate type for the method invocation * @return the double value returned from the method invocation */ private static double CallStaticDoubleMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticDoubleMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, VM_TypeReference.Double); return VM_Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticDoubleMethodA: invoke a static method that returns a double value * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation * @return the double value returned from the method invocation */ private static double CallStaticDoubleMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticDoubleMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { Object returnObj = VM_JNIHelpers.invokeWithJValue(methodID, argAddress, VM_TypeReference.Double); return VM_Reflection.unwrapDouble(returnObj); // should be a wrapper for a double value } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * CallStaticVoidMethod: invoke a static method that returns void * arguments passed using the vararg ... style * NOTE: the vararg's are not visible in the method signature here; they are saved * in the caller frame and the glue frame * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference */ private static void CallStaticVoidMethod(VM_JNIEnvironment env, int classJREF, int methodID) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticVoidMethod \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_JNIHelpers.invokeWithDotDotVarArg(methodID, VM_TypeReference.Void); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * CallStaticVoidMethodA: invoke a static method that returns void * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation */ private static void CallStaticVoidMethodV(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticVoidMethodV \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_JNIHelpers.invokeWithVarArg(methodID, argAddress, VM_TypeReference.Void); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * CallStaticVoidMethodA: invoke a static method that returns void * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class object * @param methodID id of a VM_MethodReference * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument * of the appropriate type for the method invocation */ private static void CallStaticVoidMethodA(VM_JNIEnvironment env, int classJREF, int methodID, Address argAddress) throws Exception { if (traceJNI) VM.sysWrite("JNI called: CallStaticVoidMethodA \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_JNIHelpers.invokeWithJValue(methodID, argAddress, VM_TypeReference.Void); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetStaticFieldID: return a field id which can be cached in native code and reused * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldNameAddress a raw address to a null-terminated string in C for the field name * @param descriptorAddress a raw address to a null-terminated string in C for the descriptor * @return the offset of a static field given the class, field name * and type. Return 0 if the field is not found * @exception NoSuchFieldError if the specified field cannot be found * @exception ExceptionInInitializerError if the class initializer fails * @exception OutOfMemoryError if the system runs out of memory */ private static int GetStaticFieldID(VM_JNIEnvironment env, int classJREF, Address fieldNameAddress, Address descriptorAddress) { if (traceJNI) VM.sysWrite("JNI called: GetStaticFieldID \n"); VM_Runtime.checkJNICountDownToGC(); try { Class<?> cls = (Class<?>) env.getJNIRef(classJREF); String fieldString = VM_JNIHelpers.createStringFromC(fieldNameAddress); VM_Atom fieldName = VM_Atom.findOrCreateAsciiAtom(fieldString); String descriptorString = VM_JNIHelpers.createStringFromC(descriptorAddress); VM_Atom descriptor = VM_Atom.findOrCreateAsciiAtom(descriptorString); // list of all instance fields including superclasses VM_Field[] fields = java.lang.JikesRVMSupport.getTypeForClass(cls).getStaticFields(); for (VM_Field field : fields) { if (field.getName() == fieldName && field.getDescriptor() == descriptor) { return field.getId(); } } env.recordException(new NoSuchFieldError(fieldString + ", " + descriptorString + " of " + cls)); return 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStaticObjectField: read a static field of type Object * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @return the value of the Object field, converted to a JREF index * or 0 if the fieldID is incorrect */ private static int GetStaticObjectField(VM_JNIEnvironment env, int classJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetStaticObjectField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); Object value = field.getObjectUnchecked(null); return env.pushJNIRef(value); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStaticBooleanField: read a static field of type boolean * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @return the value of the boolean field, or 0 if the fieldID is incorrect */ private static int GetStaticBooleanField(VM_JNIEnvironment env, int classJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetStaticBooleanField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getBooleanValueUnchecked(null) ? 1 : 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStaticByteField: read a static field of type byte * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @return the value of the byte field, or 0 if the fieldID is incorrect */ private static int GetStaticByteField(VM_JNIEnvironment env, int classJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetStaticByteField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getByteValueUnchecked(null); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStaticCharField: read a static field of type character * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @return the value of the character field, or 0 if the fieldID is incorrect */ private static int GetStaticCharField(VM_JNIEnvironment env, int classJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetStaticCharField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getCharValueUnchecked(null); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStaticShortField: read a static field of type short * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @return the value of the short field, or 0 if the fieldID is incorrect */ private static int GetStaticShortField(VM_JNIEnvironment env, int classJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetStaticShortField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getShortValueUnchecked(null); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStaticIntField: read a static field of type integer * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @return the value of the integer field, or 0 if the fieldID is incorrect */ private static int GetStaticIntField(VM_JNIEnvironment env, int classJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetStaticIntField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getIntValueUnchecked(null); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStaticLongField: read a static field of type long * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @return the value of the long field or 0 if the fieldID is incorrect */ private static long GetStaticLongField(VM_JNIEnvironment env, int classJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetStaticLongField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getLongValueUnchecked(null); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStaticFloatField: read a static field of type float * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @return the value of the float field or 0 if the fieldID is incorrect */ private static float GetStaticFloatField(VM_JNIEnvironment env, int classJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetStaticFloatField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getFloatValueUnchecked(null); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStaticDoubleField: read a static field of type double * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @return the value of the double field or 0 if the fieldID is incorrect */ private static double GetStaticDoubleField(VM_JNIEnvironment env, int classJREF, int fieldID) { if (traceJNI) VM.sysWrite("JNI called: GetStaticDoubleField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return field.getDoubleValueUnchecked(null); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * SetStaticObjectField: set a static field of type Object * @param env A JREF index for the JNI environment object * @param classJREF A JREF index for the {@link VM_Class} object * @param fieldID The id for the {@link VM_Field} that describes this * field * @param objectJREF A JREF index of the value to assign */ private static void SetStaticObjectField(VM_JNIEnvironment env, int classJREF, int fieldID, int objectJREF) { if (traceJNI) VM.sysWrite("JNI called: SetStaticObjectField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); Object ref = env.getJNIRef(objectJREF); field.setObjectValueUnchecked(null, ref); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetStaticBooleanField: set a static field of type boolean * @param env A JREF index for the JNI environment object * @param classJREF A JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @param fieldValue The value to assign */ private static void SetStaticBooleanField(VM_JNIEnvironment env, int classJREF, int fieldID, boolean fieldValue) { if (traceJNI) VM.sysWrite("JNI called: SetStaticBooleanField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setBooleanValueUnchecked(null, fieldValue); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetStaticByteField: set a static field of type byte * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @param fieldValue the value to assign */ private static void SetStaticByteField(VM_JNIEnvironment env, int classJREF, int fieldID, byte fieldValue) { if (traceJNI) VM.sysWrite("JNI called: SetStaticByteField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setByteValueUnchecked(null, fieldValue); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetStaticCharField: set a static field of type char * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @param fieldValue The value to assign */ private static void SetStaticCharField(VM_JNIEnvironment env, int classJREF, int fieldID, char fieldValue) { if (traceJNI) VM.sysWrite("JNI called: SetStaticCharField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setCharValueUnchecked(null, fieldValue); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetStaticShortField: set a static field of type short * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @param fieldValue The value to assign */ private static void SetStaticShortField(VM_JNIEnvironment env, int classJREF, int fieldID, short fieldValue) { if (traceJNI) VM.sysWrite("JNI called: SetStaticShortField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setShortValueUnchecked(null, fieldValue); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetStaticIntField: set a static field of type integer * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @param fieldValue The value to assign */ private static void SetStaticIntField(VM_JNIEnvironment env, int classJREF, int fieldID, int fieldValue) { if (traceJNI) VM.sysWrite("JNI called: SetStaticIntField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setIntValueUnchecked(null, fieldValue); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetStaticLongField: set a static field of type long * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @param fieldValue The value to assign */ private static void SetStaticLongField(VM_JNIEnvironment env, int classJREF, int fieldID, long fieldValue) { if (traceJNI) VM.sysWrite("JNI called: SetStaticLongField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setLongValueUnchecked(null, fieldValue); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetStaticFloatField: set a static field of type float * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @param fieldValue The value to assign */ private static void SetStaticFloatField(VM_JNIEnvironment env, int classJREF, int fieldID, float fieldValue) { if (traceJNI) VM.sysWrite("JNI called: SetStaticFloatField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setFloatValueUnchecked(null, fieldValue); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetStaticDoubleField: set a static field of type float * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the VM_Class object * @param fieldID the id for the VM_Field that describes this field * @param fieldValue The value to assign */ private static void SetStaticDoubleField(VM_JNIEnvironment env, int classJREF, int fieldID, double fieldValue) { if (traceJNI) VM.sysWrite("JNI called: SetStaticDoubleField \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); field.setDoubleValueUnchecked(null, fieldValue); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * NewString: create a String Object from C array of unicode chars * @param env A JREF index for the JNI environment object * @param uchars address of C array of 16 bit unicode characters * @param len the number of chars in the C array * @return the allocated String Object, converted to a JREF index * or 0 if an OutOfMemoryError Exception has been thrown * @exception OutOfMemoryError */ private static int NewString(VM_JNIEnvironment env, Address uchars, int len) { if (traceJNI) VM.sysWrite("JNI called: NewString \n"); VM_Runtime.checkJNICountDownToGC(); try { final char[] contents = new char[len]; VM_Memory.memcopy(VM_Magic.objectAsAddress(contents), uchars, len * 2); return env.pushJNIRef(new String(contents)); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStringLength: return the length of a String * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the String object * @return the length of the String */ private static int GetStringLength(VM_JNIEnvironment env, int objJREF) { if (traceJNI) VM.sysWrite("JNI called: GetStringLength \n"); VM_Runtime.checkJNICountDownToGC(); try { String str = (String) env.getJNIRef(objJREF); return str.length(); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStringChars: return address of buffer containing contents of a String * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the String object * @param isCopyAddress address of isCopy jboolean (an int) * @return address of a copy of the String unicode characters * and *isCopy is set to 1 (TRUE) * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetStringChars(VM_JNIEnvironment env, int objJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetStringChars \n"); VM_Runtime.checkJNICountDownToGC(); try { String str = (String) env.getJNIRef(objJREF); int len = str.length(); char[] contents = str.toCharArray(); // alloc non moving buffer in C heap for a copy of string contents Address copyBuffer = sysCall.sysMalloc(len * 2); if (copyBuffer.isZero()) { env.recordException(new OutOfMemoryError()); return Address.zero(); } VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(contents), len * 2); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); return copyBuffer; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * ReleaseStringChars: release buffer obtained via GetStringChars * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the String object * @param bufAddress address of buffer to release */ private static void ReleaseStringChars(VM_JNIEnvironment env, int objJREF, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: ReleaseStringChars \n"); VM_Runtime.checkJNICountDownToGC(); try { sysCall.sysFree(bufAddress); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * NewStringUTF: create a String Object from C array of utf8 bytes * @param env A JREF index for the JNI environment object * @param utf8bytes address of C array of 8 bit utf8 bytes * @return the allocated String Object, converted to a JREF index * or 0 if an OutOfMemoryError Exception has been thrown * @exception OutOfMemoryError if the system runs out of memory */ private static int NewStringUTF(VM_JNIEnvironment env, Address utf8bytes) { if (traceJNI) VM.sysWrite("JNI called: NewStringUTF \n"); VM_Runtime.checkJNICountDownToGC(); try { byte[] utf8array = VM_JNIHelpers.createByteArrayFromC(utf8bytes); String returnString = VM_UTF8Convert.fromUTF8(utf8array); return env.pushJNIRef(returnString); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStringUTFLength: return number of bytes to represent a String in UTF8 format * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the String object * @return number of bytes to represent in UTF8 format */ private static int GetStringUTFLength(VM_JNIEnvironment env, int objJREF) { if (traceJNI) VM.sysWrite("JNI called: GetStringUTFLength \n"); VM_Runtime.checkJNICountDownToGC(); try { String str = (String) env.getJNIRef(objJREF); return VM_UTF8Convert.utfLength(str); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetStringUTFChars: return address of buffer containing contents of a String * @param env A JREF index for the JNI environment object * @param strJREF a JREF index for the String object * @param isCopyAddress address of isCopy jboolean (an int) * @return address of a copy of the String unicode characters * and *isCopy is set to 1 (TRUE) * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetStringUTFChars(VM_JNIEnvironment env, int strJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetStringUTFChars \n"); VM_Runtime.checkJNICountDownToGC(); // briefly disable alignment checking if (VM.AlignmentChecking) { VM_SysCall.sysCall.sysDisableAlignmentChecking(); } try { String str = (String) env.getJNIRef(strJREF); byte[] utfcontents = VM_UTF8Convert.toUTF8(str); int len = utfcontents.length; int copyBufferLen = VM_Memory.alignDown(len + BYTES_IN_ADDRESS, BYTES_IN_ADDRESS); // need extra at end for storing terminator and end at word boundary // alloc non moving buffer in C heap for string contents as utf8 array // alloc extra byte for C null terminator Address copyBuffer = sysCall.sysMalloc(copyBufferLen); if (copyBuffer.isZero()) { // re-enable alignment checking if (VM.AlignmentChecking) { VM_SysCall.sysCall.sysEnableAlignmentChecking(); } env.recordException(new OutOfMemoryError()); return Address.zero(); } // store word of 0 at end, before the copy, to set C null terminator copyBuffer.plus(copyBufferLen - BYTES_IN_ADDRESS).store(Word.zero()); VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(utfcontents), len); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); // re-enable alignment checking if (VM.AlignmentChecking) { VM_SysCall.sysCall.sysEnableAlignmentChecking(); } return copyBuffer; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); // re-enable alignment checking if (VM.AlignmentChecking) { VM_SysCall.sysCall.sysEnableAlignmentChecking(); } return Address.zero(); } } /** * ReleaseStringUTFChars: release buffer obtained via GetStringUTFChars * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the String object * @param bufAddress address of buffer to release */ private static void ReleaseStringUTFChars(VM_JNIEnvironment env, int objJREF, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: ReleaseStringUTFChars \n"); VM_Runtime.checkJNICountDownToGC(); try { sysCall.sysFree(bufAddress); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetArrayLength: return array length * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @return the array length, or -1 if it's not an array */ private static int GetArrayLength(VM_JNIEnvironment env, int arrayJREF) { if (traceJNI) VM.sysWrite("JNI called: GetArrayLength \n"); VM_Runtime.checkJNICountDownToGC(); try { Object theArray = env.getJNIRef(arrayJREF); VM_Type arrayType = VM_Magic.getObjectType(theArray); return arrayType.isArrayType() ? VM_Magic.getArrayLength(theArray) : -1; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return -1; } } /** * NewObjectArray: create a new Object array * @param env A JREF index for the JNI environment object * @param length the size of the new array * @param classJREF a JREF index for the class of the element * @param initElementJREF a JREF index for the value to initialize the array elements * @return the new Object array initialized * @exception OutOfMemoryError if the system runs out of memory */ private static int NewObjectArray(VM_JNIEnvironment env, int length, int classJREF, int initElementJREF) { if (traceJNI) VM.sysWrite("JNI called: NewObjectArray \n"); VM_Runtime.checkJNICountDownToGC(); try { Object initElement = env.getJNIRef(initElementJREF); Class<?> cls = (Class<?>) env.getJNIRef(classJREF); if (cls == null) { throw new NullPointerException(); } if (length < 0) { throw new NegativeArraySizeException(); } VM_Array arrayType = java.lang.JikesRVMSupport.getTypeForClass(cls).getArrayTypeForElementType(); if (!arrayType.isInitialized(false)) { arrayType.resolve(false); arrayType.instantiate(false); arrayType.initialize(false); } Object[] newArray = (Object[]) VM_Runtime.resolvedNewArray(length, arrayType); if (initElement != null) { for (int i = 0; i < length; i++) { newArray[i] = initElement; } } return env.pushJNIRef(newArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetObjectArrayElement: retrieve an object from an object array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param index the index for the targeted element * @return the object at the specified index * @exception ArrayIndexOutOfBoundsException if the index is out of range */ private static int GetObjectArrayElement(VM_JNIEnvironment env, int arrayJREF, int index) { if (traceJNI) VM.sysWrite("JNI called: GetObjectArrayElement \n"); VM_Runtime.checkJNICountDownToGC(); try { Object[] sourceArray = (Object[]) env.getJNIRef(arrayJREF); if (sourceArray == null) { return 0; } VM_Array arrayType = VM_Magic.getObjectType(sourceArray).asArray(); if (arrayType.getElementType().isPrimitiveType()) { return 0; } if (index >= VM_Magic.getArrayLength(sourceArray)) { env.recordException(new ArrayIndexOutOfBoundsException()); return 0; } return env.pushJNIRef(sourceArray[index]); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * SetObjectArrayElement: store an object into an object array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param index the index for the targeted element * @param objectJREF a JREF index for the object to store into the array * @exception ArrayStoreException if the element types do not match * ArrayIndexOutOfBoundsException if the index is out of range */ private static void SetObjectArrayElement(VM_JNIEnvironment env, int arrayJREF, int index, int objectJREF) { if (traceJNI) VM.sysWrite("JNI called: SetObjectArrayElement \n"); VM_Runtime.checkJNICountDownToGC(); try { Object[] sourceArray = (Object[]) env.getJNIRef(arrayJREF); Object elem = env.getJNIRef(objectJREF); sourceArray[index] = elem; } catch (Throwable e) { env.recordException(e); } } /** * NewBooleanArray: create a new boolean array * @param env A JREF index for the JNI environment object * @param length the size of the new array * @return the new boolean array * @exception OutOfMemoryError if the system runs out of memory */ private static int NewBooleanArray(VM_JNIEnvironment env, int length) { if (traceJNI) VM.sysWrite("JNI called: NewBooleanArray \n"); VM_Runtime.checkJNICountDownToGC(); try { boolean[] newArray = new boolean[length]; return env.pushJNIRef(newArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewByteArray: create a new byte array * @param env A JREF index for the JNI environment object * @param length the size of the new array * @return the new byte array * @exception OutOfMemoryError if the system runs out of memory */ private static int NewByteArray(VM_JNIEnvironment env, int length) { if (traceJNI) VM.sysWrite("JNI called: NewByteArray \n"); VM_Runtime.checkJNICountDownToGC(); try { byte[] newArray = new byte[length]; return env.pushJNIRef(newArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewCharArray: create a new char array * @param env A JREF index for the JNI environment object * @param length the size of the new array * @return the new char array * @exception OutOfMemoryError if the system runs out of memory */ private static int NewCharArray(VM_JNIEnvironment env, int length) { if (traceJNI) VM.sysWrite("JNI called: NewCharArray \n"); VM_Runtime.checkJNICountDownToGC(); try { char[] newArray = new char[length]; return env.pushJNIRef(newArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewShortArray: create a new short array * @param env A JREF index for the JNI environment object * @param length the size of the new array * @return the new short array * @exception OutOfMemoryError if the system runs out of memory */ private static int NewShortArray(VM_JNIEnvironment env, int length) { if (traceJNI) VM.sysWrite("JNI called: NewShortArray \n"); VM_Runtime.checkJNICountDownToGC(); try { short[] newArray = new short[length]; return env.pushJNIRef(newArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewIntArray: create a new integer array * @param env A JREF index for the JNI environment object * @param length the size of the new array * @return the new integer array * @exception OutOfMemoryError if the system runs out of memory */ private static int NewIntArray(VM_JNIEnvironment env, int length) { if (traceJNI) VM.sysWrite("JNI called: NewIntArray \n"); VM_Runtime.checkJNICountDownToGC(); try { int[] newArray = new int[length]; return env.pushJNIRef(newArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewLongArray: create a new long array * @param env A JREF index for the JNI environment object * @param length the size of the new array * @return the new long array * @exception OutOfMemoryError if the system runs out of memory */ private static int NewLongArray(VM_JNIEnvironment env, int length) { if (traceJNI) VM.sysWrite("JNI called: NewLongArray \n"); VM_Runtime.checkJNICountDownToGC(); try { long[] newArray = new long[length]; return env.pushJNIRef(newArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewFloatArray: create a new float array * @param env A JREF index for the JNI environment object * @param length the size of the new array * @return the new float array * @exception OutOfMemoryError if the system runs out of memory */ private static int NewFloatArray(VM_JNIEnvironment env, int length) { if (traceJNI) VM.sysWrite("JNI called: NewFloatArray \n"); VM_Runtime.checkJNICountDownToGC(); try { float[] newArray = new float[length]; return env.pushJNIRef(newArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * NewDoubleArray: create a new double array * @param env A JREF index for the JNI environment object * @param length the size of the new array * @return the new long array * @exception OutOfMemoryError if the system runs out of memory */ private static int NewDoubleArray(VM_JNIEnvironment env, int length) { if (traceJNI) VM.sysWrite("JNI called: NewDoubleArray \n"); VM_Runtime.checkJNICountDownToGC(); try { double[] newArray = new double[length]; return env.pushJNIRef(newArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } /** * GetBooleanArrayElements: get all the elements of a boolean array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer * @return A pointer to the boolean array and the isCopy flag is set to true if it's a copy * or false if it's a direct pointer * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetBooleanArrayElements(VM_JNIEnvironment env, int arrayJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetBooleanArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { boolean[] sourceArray = (boolean[]) env.getJNIRef(arrayJREF); int size = sourceArray.length; // alloc non moving buffer in C heap for a copy of string contents Address copyBuffer = sysCall.sysMalloc(size); if (copyBuffer.isZero()) { env.recordException(new OutOfMemoryError()); return Address.zero(); } VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(sourceArray), size); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); return copyBuffer; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * GetByteArrayElements: get all the elements of a byte array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer * @return A pointer to the byte array and the isCopy flag is set to true if it's a copy * or false if it's a direct pointer * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetByteArrayElements(VM_JNIEnvironment env, int arrayJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetByteArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF); int size = sourceArray.length; if (MM_Interface.willNeverMove(sourceArray)) { /* return a direct pointer */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, false); return VM_Magic.objectAsAddress(sourceArray); } else { // alloc non moving buffer in C heap for a copy of string contents Address copyBuffer = sysCall.sysMalloc(size); if (copyBuffer.isZero()) { env.recordException(new OutOfMemoryError()); return Address.zero(); } VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(sourceArray), size); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); return copyBuffer; } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * GetCharArrayElements: get all the elements of a char array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer * @return A pointer to the char array and the isCopy flag is set to true if it's a copy * or false if it's a direct pointer * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetCharArrayElements(VM_JNIEnvironment env, int arrayJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetCharArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { char[] sourceArray = (char[]) env.getJNIRef(arrayJREF); int size = sourceArray.length; if (MM_Interface.willNeverMove(sourceArray)) { VM_JNIGenericHelpers.setBoolStar(isCopyAddress, false); return VM_Magic.objectAsAddress(sourceArray); } else { // alloc non moving buffer in C heap for a copy of string contents Address copyBuffer = sysCall.sysMalloc(size * BYTES_IN_CHAR); if (copyBuffer.isZero()) { env.recordException(new OutOfMemoryError()); return Address.zero(); } VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(sourceArray), size * BYTES_IN_CHAR); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); return copyBuffer; } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * GetShortArrayElements: get all the elements of a short array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer * @return A pointer to the short array and the isCopy flag is set to true if it's a copy * or false if it's a direct pointer * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetShortArrayElements(VM_JNIEnvironment env, int arrayJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetShortArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { short[] sourceArray = (short[]) env.getJNIRef(arrayJREF); int size = sourceArray.length; if (MM_Interface.willNeverMove(sourceArray)) { VM_JNIGenericHelpers.setBoolStar(isCopyAddress, false); return VM_Magic.objectAsAddress(sourceArray); } else { // alloc non moving buffer in C heap for a copy of string contents Address copyBuffer = sysCall.sysMalloc(size * BYTES_IN_SHORT); if (copyBuffer.isZero()) { env.recordException(new OutOfMemoryError()); return Address.zero(); } VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(sourceArray), size * BYTES_IN_SHORT); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); return copyBuffer; } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * GetIntArrayElements: get all the elements of an integer array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer * @return A pointer to the integer array and the isCopy flag is set to true if it's a copy * or false if it's a direct pointer * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetIntArrayElements(VM_JNIEnvironment env, int arrayJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetIntArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { int[] sourceArray = (int[]) env.getJNIRef(arrayJREF); int size = sourceArray.length; if (MM_Interface.willNeverMove(sourceArray)) { VM_JNIGenericHelpers.setBoolStar(isCopyAddress, false); return VM_Magic.objectAsAddress(sourceArray); } else { // alloc non moving buffer in C heap for a copy of array contents Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_INT); if (copyBuffer.isZero()) { env.recordException(new OutOfMemoryError()); return Address.zero(); } VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_INT); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); return copyBuffer; } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * GetLongArrayElements: get all the elements of a long array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer * @return A pointer to the long array and the isCopy flag is set to true if it's a copy * or false if it's a direct pointer * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetLongArrayElements(VM_JNIEnvironment env, int arrayJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetLongArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { long[] sourceArray = (long[]) env.getJNIRef(arrayJREF); int size = sourceArray.length; if (MM_Interface.willNeverMove(sourceArray)) { VM_JNIGenericHelpers.setBoolStar(isCopyAddress, false); return VM_Magic.objectAsAddress(sourceArray); } else { // alloc non moving buffer in C heap for a copy of string contents Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_LONG); if (copyBuffer.isZero()) { env.recordException(new OutOfMemoryError()); return Address.zero(); } VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_LONG); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); return copyBuffer; } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * GetFloatArrayElements: get all the elements of a float array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer * @return A pointer to the float array and the isCopy flag is set to true if it's a copy * or false if it's a direct pointer * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetFloatArrayElements(VM_JNIEnvironment env, int arrayJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetFloatArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { float[] sourceArray = (float[]) env.getJNIRef(arrayJREF); int size = sourceArray.length; if (MM_Interface.willNeverMove(sourceArray)) { VM_JNIGenericHelpers.setBoolStar(isCopyAddress, false); return VM_Magic.objectAsAddress(sourceArray); } else { // alloc non moving buffer in C heap for a copy of string contents Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_FLOAT); if (copyBuffer.isZero()) { env.recordException(new OutOfMemoryError()); return Address.zero(); } VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_FLOAT); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); return copyBuffer; } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * GetDoubleArrayElements: get all the elements of a double array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer * @return A pointer to the double array and the isCopy flag is set to true if it's a copy * or false if it's a direct pointer * @exception OutOfMemoryError if the system runs out of memory */ private static Address GetDoubleArrayElements(VM_JNIEnvironment env, int arrayJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetDoubleArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { double[] sourceArray = (double[]) env.getJNIRef(arrayJREF); int size = sourceArray.length; if (MM_Interface.willNeverMove(sourceArray)) { VM_JNIGenericHelpers.setBoolStar(isCopyAddress, false); return VM_Magic.objectAsAddress(sourceArray); } else { // alloc non moving buffer in C heap for a copy of string contents Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_DOUBLE); if (copyBuffer.isZero()) { env.recordException(new OutOfMemoryError()); return Address.zero(); } VM_Memory.memcopy(copyBuffer, VM_Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_DOUBLE); /* Set caller's isCopy boolean to true, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, true); return copyBuffer; } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * ReleaseBooleanArrayElements: free the native copy of the array, update changes to Java array as indicated * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param copyBufferAddress the address of the copy of the array * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: * releaseMode 0: copy back and free the buffer * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer * releaseMode 2: JNI_ABORT, free the buffer with copying back */ private static void ReleaseBooleanArrayElements(VM_JNIEnvironment env, int arrayJREF, Address copyBufferAddress, int releaseMode) { if (traceJNI) VM.sysWrite("JNI called: ReleaseBooleanArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { boolean[] sourceArray = (boolean[]) env.getJNIRef(arrayJREF); // If a direct pointer was given to the user, no need to update or release if (VM_Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { int size = sourceArray.length; // mode 0 and mode 1: copy back the buffer if ((releaseMode == 0 || releaseMode == 1) && size != 0) { for (int i = 0; i < size; i += BYTES_IN_INT) { Address addr = copyBufferAddress.plus(i); int data = addr.loadInt(); if (VM.LittleEndian) { if (i < size) sourceArray[i] = ((data) & 0x000000ff) != 0; if (i + 1 < size) sourceArray[i + 1] = ((data >>> BITS_IN_BYTE) & 0x000000ff) != 0; if (i + 2 < size) sourceArray[i + 2] = ((data >>> (2 * BITS_IN_BYTE)) & 0x000000ff) != 0; if (i + 3 < size) sourceArray[i + 3] = ((data >>> (3 * BITS_IN_BYTE)) & 0x000000ff) != 0; } else { if (i < size) sourceArray[i] = ((data >>> (3 * BITS_IN_BYTE)) & 0x000000ff) != 0; if (i + 1 < size) sourceArray[i + 1] = ((data >>> (2 * BITS_IN_BYTE)) & 0x000000ff) != 0; if (i + 2 < size) sourceArray[i + 2] = ((data >>> BITS_IN_BYTE) & 0x000000ff) != 0; if (i + 3 < size) sourceArray[i + 3] = ((data) & 0x000000ff) != 0; } } } // mode 0 and mode 2: free the buffer if (releaseMode == 0 || releaseMode == 2) { sysCall.sysFree(copyBufferAddress); } } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * ReleaseByteArrayElements: free the native copy of the array, update changes to Java array as indicated * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param copyBufferAddress the address of the copy of the array * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: * releaseMode 0: copy back and free the buffer * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer * releaseMode 2: JNI_ABORT, free the buffer with copying back */ private static void ReleaseByteArrayElements(VM_JNIEnvironment env, int arrayJREF, Address copyBufferAddress, int releaseMode) { if (traceJNI) VM.sysWrite("JNI called: ReleaseByteArrayElements releaseMode=", releaseMode); VM_Runtime.checkJNICountDownToGC(); try { byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF); // If a direct pointer was given to the user, no need to update or release if (VM_Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { int size = sourceArray.length; if (traceJNI) VM.sysWrite(" size=", size); // mode 0 and mode 1: copy back the buffer if ((releaseMode == 0 || releaseMode == 1) && size != 0) { VM_Memory.memcopy(VM_Magic.objectAsAddress(sourceArray), copyBufferAddress, size); } // mode 0 and mode 2: free the buffer if (releaseMode == 0 || releaseMode == 2) { sysCall.sysFree(copyBufferAddress); } } else { // Nothing to be done } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } if (traceJNI) VM.sysWrite("\n"); } /** * ReleaseCharArrayElements: free the native copy of the array, update changes to Java array as indicated * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param copyBufferAddress the address of the copy of the array * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: * releaseMode 0: copy back and free the buffer * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer * releaseMode 2: JNI_ABORT, free the buffer with copying back */ private static void ReleaseCharArrayElements(VM_JNIEnvironment env, int arrayJREF, Address copyBufferAddress, int releaseMode) { if (traceJNI) VM.sysWrite("JNI called: ReleaseCharArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { char[] sourceArray = (char[]) env.getJNIRef(arrayJREF); // If a direct pointer was given to the user, no need to update or release if (VM_Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { int size = sourceArray.length; // mode 0 and mode 1: copy back the buffer if ((releaseMode == 0 || releaseMode == 1) && size != 0) { VM_Memory.memcopy(VM_Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_CHAR); } // mode 0 and mode 2: free the buffer if (releaseMode == 0 || releaseMode == 2) { sysCall.sysFree(copyBufferAddress); } } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * ReleaseShortArrayElements: free the native copy of the array, update changes to Java array as indicated * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param copyBufferAddress the address of the copy of the array * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: * releaseMode 0: copy back and free the buffer * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer * releaseMode 2: JNI_ABORT, free the buffer with copying back */ private static void ReleaseShortArrayElements(VM_JNIEnvironment env, int arrayJREF, Address copyBufferAddress, int releaseMode) { if (traceJNI) VM.sysWrite("JNI called: ReleaseShortArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { short[] sourceArray = (short[]) env.getJNIRef(arrayJREF); // If a direct pointer was given to the user, no need to update or release if (VM_Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { int size = sourceArray.length; // mode 0 and mode 1: copy back the buffer if ((releaseMode == 0 || releaseMode == 1) && size != 0) { VM_Memory.memcopy(VM_Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_SHORT); } // mode 0 and mode 2: free the buffer if (releaseMode == 0 || releaseMode == 2) { sysCall.sysFree(copyBufferAddress); } } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * ReleaseIntArrayElements: free the native copy of the array, update changes to Java array as indicated * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param copyBufferAddress the address of the copy of the array * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: * releaseMode 0: copy back and free the buffer * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer * releaseMode 2: JNI_ABORT, free the buffer with copying back */ private static void ReleaseIntArrayElements(VM_JNIEnvironment env, int arrayJREF, Address copyBufferAddress, int releaseMode) { if (traceJNI) VM.sysWrite("JNI called: ReleaseIntArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { int[] sourceArray = (int[]) env.getJNIRef(arrayJREF); // If a direct pointer was given to the user, no need to update or release if (VM_Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { int size = sourceArray.length; // mode 0 and mode 1: copy back the buffer if (releaseMode == 0 || releaseMode == 1) { VM_Memory.memcopy(VM_Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_INT); } // mode 0 and mode 2: free the buffer if (releaseMode == 0 || releaseMode == 2) { sysCall.sysFree(copyBufferAddress); } } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * ReleaseLongArrayElements: free the native copy of the array, update changes to Java array as indicated * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param copyBufferAddress the address of the copy of the array * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: * releaseMode 0: copy back and free the buffer * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer * releaseMode 2: JNI_ABORT, free the buffer with copying back */ private static void ReleaseLongArrayElements(VM_JNIEnvironment env, int arrayJREF, Address copyBufferAddress, int releaseMode) { if (traceJNI) VM.sysWrite("JNI called: ReleaseLongArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { long[] sourceArray = (long[]) env.getJNIRef(arrayJREF); // If a direct pointer was given to the user, no need to update or release if (VM_Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { int size = sourceArray.length; // mode 0 and mode 1: copy back the buffer if (releaseMode == 0 || releaseMode == 1) { VM_Memory.memcopy(VM_Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_LONG); } // mode 0 and mode 2: free the buffer if (releaseMode == 0 || releaseMode == 2) { sysCall.sysFree(copyBufferAddress); } } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * ReleaseFloatArrayElements: free the native copy of the array, update changes to Java array as indicated * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param copyBufferAddress the address of the copy of the array * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: * releaseMode 0: copy back and free the buffer * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer * releaseMode 2: JNI_ABORT, free the buffer with copying back */ private static void ReleaseFloatArrayElements(VM_JNIEnvironment env, int arrayJREF, Address copyBufferAddress, int releaseMode) { if (traceJNI) VM.sysWrite("JNI called: ReleaseFloatArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { float[] sourceArray = (float[]) env.getJNIRef(arrayJREF); // If a direct pointer was given to the user, no need to update or release if (VM_Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { int size = sourceArray.length; // mode 0 and mode 1: copy back the buffer if (releaseMode == 0 || releaseMode == 1) { VM_Memory.memcopy(VM_Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_FLOAT); } // mode 0 and mode 2: free the buffer if (releaseMode == 0 || releaseMode == 2) { sysCall.sysFree(copyBufferAddress); } } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * ReleaseDoubleArrayElements: free the native copy of the array, update changes to Java array as indicated * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param copyBufferAddress the address of the copy of the array * @param releaseMode one of 3 codes to indicate whether to copy back or free the array: * releaseMode 0: copy back and free the buffer * releaseMode 1: JNI_COMMIT, copy back but do not free the buffer * releaseMode 2: JNI_ABORT, free the buffer with copying back */ private static void ReleaseDoubleArrayElements(VM_JNIEnvironment env, int arrayJREF, Address copyBufferAddress, int releaseMode) { if (traceJNI) VM.sysWrite("JNI called: ReleaseDoubleArrayElements \n"); VM_Runtime.checkJNICountDownToGC(); try { double[] sourceArray = (double[]) env.getJNIRef(arrayJREF); // If a direct pointer was given to the user, no need to update or release if (VM_Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) { int size = sourceArray.length; // mode 0 and mode 1: copy back the buffer if (releaseMode == 0 || releaseMode == 1) { VM_Memory.memcopy(VM_Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_DOUBLE); } // mode 0 and mode 2: free the buffer if (releaseMode == 0 || releaseMode == 2) { sysCall.sysFree(copyBufferAddress); } } } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetBooleanArrayRegion: copy a region of the array into the native buffer * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the destination address in native to copy to * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void GetBooleanArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: GetBooleanArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { boolean[] sourceArray = (boolean[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(bufAddress, VM_Magic.objectAsAddress(sourceArray).plus(startIndex), length); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetByteArrayRegion: copy a region of the array into the native buffer * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the destination address in native to copy to * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void GetByteArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: GetByteArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(bufAddress, VM_Magic.objectAsAddress(sourceArray).plus(startIndex), length); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetCharArrayRegion: copy a region of the array into the native buffer * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the destination address in native to copy to * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void GetCharArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: GetCharArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { char[] sourceArray = (char[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(bufAddress, VM_Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_CHAR), length << LOG_BYTES_IN_CHAR); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetShortArrayRegion: copy a region of the array into the native buffer * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the destination address in native to copy to * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void GetShortArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: GetShortArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { short[] sourceArray = (short[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(bufAddress, VM_Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_SHORT), length << LOG_BYTES_IN_SHORT); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetIntArrayRegion: copy a region of the array into the native buffer * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the destination address in native to copy to * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void GetIntArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: GetIntArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { int[] sourceArray = (int[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(bufAddress, VM_Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_INT), length << LOG_BYTES_IN_INT); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetLongArrayRegion: copy a region of the array into the native buffer * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the destination address in native to copy to * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void GetLongArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: GetLongArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { long[] sourceArray = (long[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(bufAddress, VM_Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_LONG), length << LOG_BYTES_IN_LONG); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetFloatArrayRegion: copy a region of the array into the native buffer * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the destination address in native to copy to * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void GetFloatArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: GetFloatArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { float[] sourceArray = (float[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(bufAddress, VM_Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_FLOAT), length << LOG_BYTES_IN_FLOAT); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetDoubleArrayRegion: copy a region of the array into the native buffer * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the source array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the destination address in native to copy to * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void GetDoubleArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: GetDoubleArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { double[] sourceArray = (double[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > sourceArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(bufAddress, VM_Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_DOUBLE), length << LOG_BYTES_IN_DOUBLE); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetBooleanArrayRegion: copy a region of the native buffer into the array (1 byte element) * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the destination array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the source address in native to copy from * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void SetBooleanArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: SetBooleanArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { boolean[] destinationArray = (boolean[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(VM_Magic.objectAsAddress(destinationArray).plus(startIndex), bufAddress, length); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetByteArrayRegion: copy a region of the native buffer into the array (1 byte element) * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the destination array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the source address in native to copy from * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void SetByteArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: SetByteArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { byte[] destinationArray = (byte[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(VM_Magic.objectAsAddress(destinationArray).plus(startIndex), bufAddress, length); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetCharArrayRegion: copy a region of the native buffer into the array (2 byte element) * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the destination array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the source address in native to copy from * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void SetCharArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: SetCharArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { char[] destinationArray = (char[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(VM_Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_CHAR), bufAddress, length << LOG_BYTES_IN_CHAR); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetShortArrayRegion: copy a region of the native buffer into the array (2 byte element) * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the destination array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the source address in native to copy from * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void SetShortArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: SetShortArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { short[] destinationArray = (short[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(VM_Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_SHORT), bufAddress, length << LOG_BYTES_IN_SHORT); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetIntArrayRegion: copy a region of the native buffer into the array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the destination array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the source address in native to copy from * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void SetIntArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: SetIntArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { int[] destinationArray = (int[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(VM_Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_INT), bufAddress, length << LOG_BYTES_IN_INT); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetLongArrayRegion: copy a region of the native buffer into the array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the destination array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the source address in native to copy from * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void SetLongArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: SetLongArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { long[] destinationArray = (long[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(VM_Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_LONG), bufAddress, length << LOG_BYTES_IN_LONG); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetFloatArrayRegion: copy a region of the native buffer into the array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the destination array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the source address in native to copy from * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void SetFloatArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: SetFloatArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { float[] destinationArray = (float[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(VM_Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_FLOAT), bufAddress, length << LOG_BYTES_IN_FLOAT); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * SetDoubleArrayRegion: copy a region of the native buffer into the array * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the destination array * @param startIndex the starting index to copy * @param length the number of elements to copy * @param bufAddress the source address in native to copy from * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid */ private static void SetDoubleArrayRegion(VM_JNIEnvironment env, int arrayJREF, int startIndex, int length, Address bufAddress) { if (traceJNI) VM.sysWrite("JNI called: SetDoubleArrayRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { double[] destinationArray = (double[]) env.getJNIRef(arrayJREF); if ((startIndex < 0) || (startIndex + length > destinationArray.length)) { env.recordException(new ArrayIndexOutOfBoundsException()); return; } VM_Memory.memcopy(VM_Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_DOUBLE), bufAddress, length << LOG_BYTES_IN_DOUBLE); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * RegisterNatives: registers implementation of native methods * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class to register native methods in * @param methodsAddress the address of an array of native methods to be registered * @param nmethods the number of native methods in the array * @return 0 is successful -1 if failed * @exception NoSuchMethodError if a specified method cannot be found or is not native */ private static int RegisterNatives(VM_JNIEnvironment env, int classJREF, Address methodsAddress, int nmethods) { if (traceJNI) VM.sysWrite("JNI called: RegisterNatives \n"); VM_Runtime.checkJNICountDownToGC(); try { // get the target class Class<?> jcls = (Class<?>) env.getJNIRef(classJREF); VM_Type type = java.lang.JikesRVMSupport.getTypeForClass(jcls); if (!type.isClassType()) { env.recordException(new NoSuchMethodError()); return 0; } VM_Class klass = type.asClass(); if (!klass.isInitialized(false)) { VM_Runtime.initializeClassForDynamicLink(klass); } // Create list of methods and verify them to avoid partial success VM_NativeMethod[] methods = new VM_NativeMethod[nmethods]; AddressArray symbols = AddressArray.create(nmethods); Address curMethod = methodsAddress; for (int i = 0; i < nmethods; i++) { String methodString = VM_JNIHelpers.createStringFromC(curMethod.loadAddress()); VM_Atom methodName = VM_Atom.findOrCreateAsciiAtom(methodString); String sigString = VM_JNIHelpers.createStringFromC(curMethod.loadAddress(Offset.fromIntSignExtend(BYTES_IN_ADDRESS))); VM_Atom sigName = VM_Atom.findOrCreateAsciiAtom(sigString); // Find the target method VM_Method meth = klass.findDeclaredMethod(methodName, sigName); if (meth == null || !meth.isNative()) { env.recordException(new NoSuchMethodError(klass + ": " + methodName + " " + sigName)); return -1; } methods[i] = (VM_NativeMethod) meth; symbols.set(i, curMethod.loadAddress(Offset.fromIntSignExtend(BYTES_IN_ADDRESS * 2))); curMethod = curMethod.plus(3 * BYTES_IN_ADDRESS); } // Register methods for (int i = 0; i < nmethods; i++) { methods[i].registerNativeSymbol(symbols.get(i)); } return 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return -1; } } /** * UnregisterNatives: unregisters native methods * @param env A JREF index for the JNI environment object * @param classJREF a JREF index for the class to register native methods in * @return 0 is successful -1 if failed */ private static int UnregisterNatives(VM_JNIEnvironment env, int classJREF) { if (traceJNI) VM.sysWrite("JNI called: UnregisterNatives \n"); VM_Runtime.checkJNICountDownToGC(); try { // get the target class Class<?> jcls = (Class<?>) env.getJNIRef(classJREF); VM_Type type = java.lang.JikesRVMSupport.getTypeForClass(jcls); if (!type.isClassType()) { env.recordException(new NoClassDefFoundError()); return -1; } VM_Class klass = type.asClass(); if (!klass.isInitialized(false)) { return 0; } klass.unregisterNativeMethods(); return 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return -1; } } /** * MonitorEnter * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object to lock * @return 0 if the object is locked successfully, -1 if not */ private static int MonitorEnter(VM_JNIEnvironment env, int objJREF) { if (traceJNI) VM.sysWrite("JNI called: MonitorEnter \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_ObjectModel.genericLock(obj); return 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); return -1; } } /** * MonitorExit * @param env A JREF index for the JNI environment object * @param objJREF a JREF index for the object to unlock * @return 0 if the object is unlocked successfully, -1 if not */ private static int MonitorExit(VM_JNIEnvironment env, int objJREF) { if (traceJNI) VM.sysWrite("JNI called: MonitorExit \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj = env.getJNIRef(objJREF); VM_ObjectModel.genericUnlock(obj); return 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); return -1; } } private static int GetJavaVM(VM_JNIEnvironment env, Address StarStarJavaVM) { if (traceJNI) VM.sysWrite("JNI called: GetJavaVM \n"); VM_Runtime.checkJNICountDownToGC(); try { if (traceJNI) VM.sysWriteln(StarStarJavaVM); Address JavaVM = VM_BootRecord.the_boot_record.sysJavaVM; StarStarJavaVM.store(JavaVM); return 0; } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); return -1; } } /******************************************************************* * These functions were added in Java 2 (JNI 1.2) */ /** * FromReflectedMethod * @param env A JREF index for the JNI environment object * @param methodJREF a JREF index for the java.lang.reflect.Method or * java.lang.reflect.Constructor object. * @return the jmethodID corresponding to methodJREF */ private static int FromReflectedMethod(VM_JNIEnvironment env, int methodJREF) { if (traceJNI) VM.sysWrite("JNI called: FromReflectedMethod \n"); VM_Runtime.checkJNICountDownToGC(); Object methodObj = env.getJNIRef(methodJREF); VM_Method meth; if (methodObj instanceof Constructor) { meth = java.lang.reflect.JikesRVMSupport.getMethodOf((Constructor<?>) methodObj); } else { meth = java.lang.reflect.JikesRVMSupport.getMethodOf((Method) methodObj); } if (traceJNI) VM.sysWrite("got method " + meth + "\n"); return meth.getId(); } /** * FromReflectedField * @param env A JREF index for the JNI environment object * @param fieldJREF a JREF index for a java.lang.reflect.Field methodID * @return the jfieldID corresponding to fieldJREF * */ private static int FromReflectedField(VM_JNIEnvironment env, int fieldJREF) { if (traceJNI) VM.sysWrite("JNI called: FromReflectedField \n"); VM_Runtime.checkJNICountDownToGC(); Field fieldObj = (Field) env.getJNIRef(fieldJREF); VM_Field f = java.lang.reflect.JikesRVMSupport.getFieldOf(fieldObj); if (traceJNI) VM.sysWrite("got field " + f + "\n"); return f.getId(); } /** * ToReflectedMethod * @param env A JREF index for the JNI environment object * @param clsJREF The JREF index of the class from which methodID was * derived. * @param methodID a jmethodID to turn into a reflected method * @param isStatic argument that is not specified in Sun's JNI 1.2 spec, * but IS present in the 1.4.2 JDK's implementation! Our * implementation will just ignore it, in any case. This is a * good example of why the same entity * shouldn't get to write both the spec and the reference * implementation. * @return a JREF index for the java.lang.reflect.Method or * java.lang.reflect.Constructor object associated with methodID. */ private static int ToReflectedMethod(VM_JNIEnvironment env, int clsJREF, int methodID, boolean isStatic) { if (traceJNI) VM.sysWrite("JNI called: ToReflectedMethod \n"); VM_Runtime.checkJNICountDownToGC(); VM_Method targetMethod = VM_MemberReference.getMemberRef(methodID).asMethodReference().resolve(false); Object ret; if (targetMethod.isObjectInitializer()) { ret = java.lang.reflect.JikesRVMSupport.createConstructor(targetMethod); } else { ret = java.lang.reflect.JikesRVMSupport.createMethod(targetMethod); } return env.pushJNIRef(ret); } /** * ToReflectedField * @param env A JREF index for the JNI environment object * @param clsJREF The JREF index of the class from which fieldID was * derived. * @param fieldID a jfieldID * @param isStatic argument that is not specified in Sun's JNI 1.2 spec, * but IS present in the 1.4.2 JDK's implementation! Our * implementation will just ignore it, in any case. This is a * good example of why the same entity * shouldn't get to write both the spec and the reference * implementation. * @return a JREF index for the java.lang.reflect.Field object associated * with fieldID. */ private static int ToReflectedField(VM_JNIEnvironment env, int clsJREF, int fieldID, boolean isStatic) { if (traceJNI) VM.sysWrite("JNI called: ToReflectedField \n"); VM_Runtime.checkJNICountDownToGC(); VM_Field field = VM_MemberReference.getMemberRef(fieldID).asFieldReference().resolve(false); return env.pushJNIRef(java.lang.reflect.JikesRVMSupport.createField(field)); } /** Push a local frame for local references. * We could implement this more fancily, but it seems that we hardly need * to, since we allow an unlimited number of local refs. One could force * running out of memory in a long-running loop in JNI, of course. */ private static int PushLocalFrame(VM_JNIEnvironment env, int capacity) { if (traceJNI) VM.sysWrite("JNI called: PushLocalFrame \n"); VM_Runtime.checkJNICountDownToGC(); return 0; // OK } /** Push a local frame for local references. * We could implement this more fancily, but it seems that we hardly need * to, since we allow an unlimited number of local refs. One could force * running out of memory in a long-running loop in JNI, of course, and this * might save us from that. Let's hold off until we need it. TODO. * * @return a local reference in the old frame that refers to the same object * as oldJREF. */ private static int PopLocalFrame(VM_JNIEnvironment env, int resultJREF) { if (traceJNI) VM.sysWrite("JNI called: PopLocalFrame \n"); VM_Runtime.checkJNICountDownToGC(); // do nothing. return resultJREF; } /** * NewLocalRef * * @param env A JREF index for the JNI environment object * @param oldJREF JREF index of an existing reference. * @return a new local reference that refers to the same object as oldJREF. * C NULL pointer if the oldJREF refers to null. */ private static int NewLocalRef(VM_JNIEnvironment env, int oldJREF) { if (traceJNI) VM.sysWrite("JNI called: NewLocalRef \n"); VM_Runtime.checkJNICountDownToGC(); Object oldObj = env.getJNIRef(oldJREF); /* pushJNIRef automatically handles null refs properly. */ return env.pushJNIRef(oldObj); } /** * EnsureLocalCapacity * * @param env A JREF index for the JNI environment object * @param capacity how many more local references do we want to ensure can * be created? * @return 0 on success. The JNI spec says that on failure this throws * OutOfMemoryError and returns a negative number. But we don't have to * worry about that at all. */ private static int EnsureLocalCapacity(VM_JNIEnvironment env, int capacity) { if (traceJNI) VM.sysWrite("JNI called: EnsureLocalCapacity \n"); VM_Runtime.checkJNICountDownToGC(); return 0; // success! } /** GetStringRegion: Copy a region of Unicode characters from a string to * the given buffer. * * @param env A JREF index for the JNI environment object * @param strJREF a JREF index for the String object * @param start index to start reading characters from the string * @param len how many characters to read * @param buf the buffer to copy the region into * @exception StringIndexOutOfBoundsException if asked for an out-of-range * region of the string. */ private static void GetStringRegion(VM_JNIEnvironment env, int strJREF, int start, int len, Address buf) { if (traceJNI) VM.sysWrite("JNI called: GetStringRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { String str = (String) env.getJNIRef(strJREF); char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str); int strOffset = java.lang.JikesRVMSupport.getStringOffset(str); int strLen = java.lang.JikesRVMSupport.getStringLength(str); if (strLen < start + len) { env.recordException(new StringIndexOutOfBoundsException()); return; } Address strBase = VM_Magic.objectAsAddress(strChars); Address srcBase = strBase.plus(strOffset * 2).plus(start * 2); VM_Memory.memcopy(buf, srcBase, len * 2); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** GetStringUTFRegion: Copy a region of Unicode characters from a string to * the given buffer, as UTF8 characters. * * @param env A JREF index for the JNI environment object * @param strJREF a JREF index for the String object * @param start index to start reading characters from the string * @param len how many characters to read from the string * @param buf the buffer to copy the region into -- assume it's big enough * @exception StringIndexOutOfBoundsException if asked for an out-of-range * region of the string. */ private static void GetStringUTFRegion(VM_JNIEnvironment env, int strJREF, int start, int len, Address buf) { if (traceJNI) VM.sysWrite("JNI called: GetStringUTFRegion \n"); VM_Runtime.checkJNICountDownToGC(); try { String str = (String) env.getJNIRef(strJREF); char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str); int strOffset = java.lang.JikesRVMSupport.getStringOffset(str); int strLen = java.lang.JikesRVMSupport.getStringLength(str); if (strLen < start + len) { env.recordException(new StringIndexOutOfBoundsException()); return; } /* XXX TODO This is pretty inefficient. We create another String, * just to feed it to the UTF8 method, but I'm feeling lazy and * don't want to go into writing another interface to * VM_UTF8Convert.toUTF8() to handle ranges of char arrays. */ String region = new String(strChars, strOffset + start, len); byte[] utfcontents = VM_UTF8Convert.toUTF8(region); VM_Memory.memcopy(buf, VM_Magic.objectAsAddress(utfcontents), utfcontents.length); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** * GetPrimitiveArrayCritical: return a direct pointer to the primitive array * and disable GC so that the array will not be moved. This function * is intended to be paired with the ReleasePrimitiveArrayCritical function * within a short time so that GC will be reenabled * * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the primitive array in Java * @param isCopyAddress address of isCopy jboolean (an int) * @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. * @exception OutOfMemoryError is specified but will not be thrown in this implementation * since no copy will be made */ private static Address GetPrimitiveArrayCritical(VM_JNIEnvironment env, int arrayJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetPrimitiveArrayCritical \n"); VM_Runtime.checkJNICountDownToGC(); try { Object primitiveArray = env.getJNIRef(arrayJREF); // not an array, return null if (!primitiveArray.getClass().isArray()) { return Address.zero(); } /* Set caller's isCopy boolean to false, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, false); // For array of primitive, return the object address, which is the array itself VM.disableGC(true); return VM_Magic.objectAsAddress(primitiveArray); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } /** * ReleasePrimitiveArrayCritical: this function is intended to be paired * with the GetPrimitiveArrayCritical function. * Since the native code has direct access * to the array, no copyback update is necessary; GC is simply reenabled. * @param env A JREF index for the JNI environment object * @param arrayJREF a JREF index for the primitive array in Java * @param arrayCopyAddress * @param mode a flag indicating whether to update the Java array with the * copy and whether to free the copy. For this implementation, * no copy was made so this flag has no effect. */ private static void ReleasePrimitiveArrayCritical(VM_JNIEnvironment env, int arrayJREF, Address arrayCopyAddress, int mode) { if (traceJNI) VM.sysWrite("JNI called: ReleasePrimitiveArrayCritical \n"); VM_Runtime.checkJNICountDownToGC(); try { VM.enableGC(true); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } /** GetStringCritical * Like GetStringChars and ReleaseStringChars, but in some VM environments * the VM may be able to avoid making a copy. Native code must not issue * arbitrary JNI calls and must not cause the current thread to block. * * @param env A JREF index for the JNI environment object * @param strJREF a JREF index for the string in Java * @param isCopyAddress address of isCopy jboolean (an int) * @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. */ private static Address GetStringCritical(VM_JNIEnvironment env, int strJREF, Address isCopyAddress) { if (traceJNI) VM.sysWrite("JNI called: GetStringCritical \n"); VM_Runtime.checkJNICountDownToGC(); String str = (String) env.getJNIRef(strJREF); char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str); int strOffset = java.lang.JikesRVMSupport.getStringOffset(str); /* Set caller's isCopy boolean to false, if we got a valid (non-null) address */ VM_JNIGenericHelpers.setBoolStar(isCopyAddress, false); VM.disableGC(true); Address strBase = VM_Magic.objectAsAddress(strChars); return strBase.plus(strOffset * 2); } /** * ReleaseStringCritical: this function is intended to be paired with the * GetStringCritical function. Since the native code has direct access * to the string's backing array of characters, no copyback update is * necessary; GC is simply reenabled. * * @param env A JREF index for the JNI environment object * @param strJREF a JREF index for the string in Java (ignored) * @param carray the pointer returned by GetStringCritical (ignored) */ private static void ReleaseStringCritical(VM_JNIEnvironment env, int strJREF, Address carray) { if (traceJNI) VM.sysWrite("JNI called: ReleaseStringCritical \n"); VM_Runtime.checkJNICountDownToGC(); try { VM.enableGC(true); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } private static int NewWeakGlobalRef(VM_JNIEnvironment env, int objectJREF) { if (traceJNI) VM.sysWrite("JNI called: NewWeakGlobalRef \n"); VM_Runtime.checkJNICountDownToGC(); try { Object obj1 = env.getJNIRef(objectJREF); return VM_JNIGlobalRefTable.newWeakRef(obj1); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } private static void DeleteWeakGlobalRef(VM_JNIEnvironment env, int refJREF) { if (traceJNI) VM.sysWrite("JNI called: DeleteWeakGlobalRef \n"); VM_Runtime.checkJNICountDownToGC(); try { VM_JNIGlobalRefTable.deleteWeakRef(refJREF); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); } } private static int ExceptionCheck(VM_JNIEnvironment env) { if (traceJNI) VM.sysWrite("JNI called: ExceptionCheck \n"); VM_Runtime.checkJNICountDownToGC(); return env.getException() == null ? 0 : 1; } /******************************************************************* * These functions are in JNI 1.4 */ private static int NewDirectByteBuffer(VM_JNIEnvironment env, Address address, long capacity) { if (traceJNI) VM.sysWrite("JNI called: NewDirectByteBuffer \n"); VM_Runtime.checkJNICountDownToGC(); try { Buffer buffer = java.nio.JikesRVMSupport.newDirectByteBuffer(address, capacity); return env.pushJNIRef(buffer); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return 0; } } private static Address GetDirectBufferAddress(VM_JNIEnvironment env, int bufJREF) { if (traceJNI) VM.sysWrite("JNI called: GetDirectBufferAddress \n"); VM_Runtime.checkJNICountDownToGC(); try { Buffer buffer = (Buffer) env.getJNIRef(bufJREF); //if (buffer instanceof ByteBuffer) { // VM.sysWrite("ByteBuffer, "); // if (((ByteBuffer)buffer).isDirect()) // VM.sysWrite("Direct, "); //} //VM.sysWriteln("Direct buffer address = ",result); return java.nio.JikesRVMSupport.getDirectBufferAddress(buffer); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return Address.zero(); } } private static long GetDirectBufferCapacity(VM_JNIEnvironment env, int bufJREF) { if (traceJNI) VM.sysWrite("JNI called: GetDirectBufferCapacity \n"); VM_Runtime.checkJNICountDownToGC(); try { Buffer buffer = (Buffer) env.getJNIRef(bufJREF); return buffer.capacity(); } catch (Throwable unexpected) { if (traceJNI) unexpected.printStackTrace(System.err); env.recordException(unexpected); return -1; } } /******************************************************************* * Empty Slots */ private static int reserved0(VM_JNIEnvironment env) { VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n"); VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP); return -1; } private static int reserved1(VM_JNIEnvironment env) { VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n"); VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP); return -1; } private static int reserved2(VM_JNIEnvironment env) { VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n"); VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP); return -1; } private static int reserved3(VM_JNIEnvironment env) { VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n"); VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP); return -1; } }