Class* rvmFindClassByDescriptor(Env* env, const char* desc, ClassLoader* classLoader) { switch (desc[0]) { case 'Z': return prim_Z; case 'B': return prim_B; case 'C': return prim_C; case 'S': return prim_S; case 'I': return prim_I; case 'J': return prim_J; case 'F': return prim_F; case 'D': return prim_D; case 'V': return prim_V; case '[': return rvmFindClassUsingLoader(env, desc, classLoader); } // desc[0] == 'L' jint length = strlen(desc); char* className = rvmAllocateMemoryAtomic(env, length - 2 + 1); if (!className) return NULL; strncpy(className, &desc[1], length - 2); return rvmFindClassUsingLoader(env, className, classLoader); }
Class* Java_java_lang_Class_classForName(Env* env, Class* cls, Object* className, jboolean initializeBoolean, ClassLoader* classLoader) { if (!className) { rvmThrowNullPointerException(env); return NULL; } char* classNameUTF = toBinaryName(env, className); if (!classNameUTF) return NULL; Class* clazz = rvmFindClassUsingLoader(env, classNameUTF, classLoader); if (!clazz) { char* p = classNameUTF; while (*p != '\0') { if (*p == '/') *p = '.'; p++; } WARNF("Class.forName() failed to load '%s'. " "Use the -forcelinkclasses command line option " "or add <forceLinkClasses><pattern>%s</pattern></forceLinkClasses> " "to your robovm.xml file to link it in.", classNameUTF, classNameUTF); return NULL; } if (initializeBoolean) { rvmInitialize(env, clazz); if (rvmExceptionCheck(env)) return NULL; } return clazz; }
jboolean rvmInitMethods(Env* env) { if (rvmInitMutex(&nativeLibsLock) != 0) { return FALSE; } if (rvmInitMutex(&threadStackTraceLock) != 0) { return FALSE; } java_lang_StackTraceElement = rvmFindClassUsingLoader(env, "java/lang/StackTraceElement", NULL); if (!java_lang_StackTraceElement) { return FALSE; } java_lang_StackTraceElement_constructor = rvmGetInstanceMethod(env, java_lang_StackTraceElement, "<init>", "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V"); if (!java_lang_StackTraceElement_constructor) { return FALSE; } empty_java_lang_StackTraceElement_array = rvmNewObjectArray(env, 0, java_lang_StackTraceElement, NULL, NULL); if (!empty_java_lang_StackTraceElement_array) { return FALSE; } if (!rvmAddObjectGCRoot(env, (Object*) empty_java_lang_StackTraceElement_array)) { return FALSE; } return TRUE; }
Object* Java_java_lang_ClassCache_loadReflectionAccess(Env* env, JClass* c) { JClass* ao = rvmFindClassUsingLoader(env, "java/lang/reflect/AccessibleObject", NULL); if (!ao) return NULL; ClassField* f = rvmGetClassField(env, ao, "REFLECTION_ACCESS", "Lorg/robovm/rt/ReflectionAccess;"); if (!f) return NULL; return rvmGetObjectClassFieldValue(env, ao, f); }
jboolean rvmRun(Env* env) { Options* options = env->vm->options; Class* clazz = NULL; clazz = rvmFindClassUsingLoader(env, options->mainClass, systemClassLoader); if (clazz) { Method* method = rvmGetClassMethod(env, clazz, "main", "([Ljava/lang/String;)V"); if (method) { ObjectArray* args = rvmNewObjectArray(env, options->commandLineArgsCount, java_lang_String, NULL, NULL); if (args) { jint i = 0; for (i = 0; i < args->length; i++) { // TODO: Don't assume modified UTF-8 args->values[i] = rvmNewStringUTF(env, options->commandLineArgs[i], -1); if (!args->values[i]) { args = NULL; break; } } if (args) rvmCallVoidClassMethod(env, clazz, method, args); } } } Object* throwable = rvmExceptionOccurred(env); rvmDetachCurrentThread(env->vm, TRUE); return throwable == NULL ? TRUE : FALSE; }
static Interface* loadInterfaces(Env* env, Class* clazz) { ClassInfoHeader* header = lookupClassInfo(env, clazz->name, !clazz->classLoader || !clazz->classLoader->parent ? _bcBootClassesHash : _bcClassesHash); if (!header) return NULL; ClassInfo ci; jint i; void* p = header; readClassInfo(&p, &ci); Interface* first = NULL; for (i = 0; i < ci.interfaceCount; i++) { const char* interfaceName = readInterfaceName(&p); Class* interfaceClass = rvmFindClassUsingLoader(env, interfaceName, clazz->classLoader); if (!interfaceClass) goto error; Interface* interf = rvmAllocateInterface(env, interfaceClass); if (!interf) goto error; LL_APPEND(first, interf); // Interfaces has to be in the correct order so we need to use the slower LL_APPEND } return first; error: while (first) { Interface* next = first->next; rvmFreeMemoryUncollectable(env, first); first = next; } return NULL; }
jboolean rvmRun(Env* env) { Options* options = env->vm->options; Class* clazz = NULL; rvmHookBeforeAppEntryPoint(env, options->mainClass); clazz = rvmFindClassUsingLoader(env, options->mainClass, systemClassLoader); if (clazz) { Method* method = rvmGetClassMethod(env, clazz, "main", "([Ljava/lang/String;)V"); if (method) { ObjectArray* args = rvmNewObjectArray(env, options->commandLineArgsCount, java_lang_String, NULL, NULL); if (args) { jint i = 0; for (i = 0; i < args->length; i++) { // TODO: Don't assume modified UTF-8 args->values[i] = rvmNewStringUTF(env, options->commandLineArgs[i], -1); if (!args->values[i]) { args = NULL; break; } } if (args) { rvmCallVoidClassMethod(env, clazz, method, args); } } } } return rvmDestroyVM(env->vm); }
ClassLoader* rvmGetSystemClassLoader(Env* env) { Class* holder = rvmFindClassUsingLoader(env, "java/lang/ClassLoader$SystemClassLoader", NULL); if (!holder) return NULL; ClassField* field = rvmGetClassField(env, holder, "loader", "Ljava/lang/ClassLoader;"); if (!field) return NULL; return (ClassLoader*) rvmGetObjectClassFieldValue(env, holder, field); }
static Class* createClass(Env* env, ClassInfoHeader* header, ClassLoader* classLoader) { ClassInfo ci; void* p = header; readClassInfo(&p, &ci); Class* superclass = NULL; if (ci.superclassName) { superclass = rvmFindClassUsingLoader(env, ci.superclassName, classLoader); if (!superclass) return NULL; } rvmObtainClassLock(env); Class* clazz = rvmAllocateClass(env, header->className, superclass, classLoader, ci.access, header->typeInfo, header->vitable, header->itables, header->classDataSize, header->instanceDataSize, header->instanceDataOffset, header->classRefCount, header->instanceRefCount, ci.attributes, header->initializer); if (clazz) { if (!rvmRegisterClass(env, clazz)) { rvmReleaseClassLock(env); return NULL; } header->clazz = clazz; rvmHookClassLoaded(env, clazz, (void*)header); } rvmReleaseClassLock(env); return clazz; }
static void wrapClassNotFoundException(Env* env, const char* className) { Object* exception = rvmExceptionOccurred(env); if (exception && exception->clazz == java_lang_ClassNotFoundException) { // If ClassNotFoundException is thrown we have to wrap it in a NoClassDefFoundError exception = rvmExceptionClear(env); Method* constructor = rvmGetInstanceMethod(env, java_lang_NoClassDefFoundError, "<init>", "(Ljava/lang/String;)V"); if (!constructor) return; Object* message = rvmNewStringUTF(env, className, -1); if (!message) return; Object* wrappedException = rvmNewObject(env, java_lang_NoClassDefFoundError, constructor, message); if (!wrappedException) return; Class* java_lang_StackTraceElement = rvmFindClassUsingLoader(env, "java/lang/StackTraceElement", NULL); if (!java_lang_StackTraceElement) return; ObjectArray* stackTrace = rvmNewObjectArray(env, 0, java_lang_StackTraceElement, NULL, NULL); if (!stackTrace) return; Method* setStackTrace = rvmGetInstanceMethod(env, java_lang_Throwable, "setStackTrace", "([Ljava/lang/StackTraceElement;)V"); if (!setStackTrace) return; rvmCallVoidInstanceMethod(env, wrappedException, setStackTrace, stackTrace); if (rvmExceptionCheck(env)) return; Method* initCause = rvmGetInstanceMethod(env, java_lang_NoClassDefFoundError, "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;"); if (!initCause) return; rvmCallObjectInstanceMethod(env, wrappedException, initCause, exception); if (!rvmExceptionCheck(env)) rvmThrow(env, wrappedException); } }
ObjectArray* Java_java_lang_reflect_Method_getExceptionTypes(Env* env, Class* clazz, jlong methodPtr) { Method* method = (Method*) LONG_TO_PTR(methodPtr); Class* java_lang_reflect_Proxy = rvmFindClassUsingLoader(env, "java/lang/reflect/Proxy", NULL); if (method->clazz->superclass == java_lang_reflect_Proxy) { return rvmAttributeGetExceptions(env, ((ProxyMethod*) method)->proxiedMethod); } return rvmAttributeGetExceptions(env, method); }
static jboolean getDeclaringClassIterator(Env* env, char* innerClass, char* outerClass, char* innerName, jint access, void* data) { Class** result = (Class**) ((void**) data)[0]; Class* clazz = (Class*) ((void**) data)[1]; if (innerClass && outerClass && !strcmp(innerClass, clazz->name)) { *result = rvmFindClassUsingLoader(env, outerClass, clazz->classLoader); return FALSE; // Stop iterating } return TRUE; // Continue with next attribute }
Object* _bcLdcArrayClass(Env* env, Class** arrayClassPtr, char* name) { Class* arrayClass = *arrayClassPtr; if (arrayClass) return (Object*) arrayClass; ENTER; arrayClass = rvmFindClassUsingLoader(env, name, systemClassLoader); wrapClassNotFoundException(env, name); if (!rvmExceptionCheck(env)) { *arrayClassPtr = arrayClass; } LEAVE((Object*) arrayClass); }
Method* getMethodFromMethodObject(Env* env, Object* methodObject) { if (!java_lang_reflect_Method) { java_lang_reflect_Method = rvmFindClassUsingLoader(env, "java/lang/reflect/Method", NULL); if (!java_lang_reflect_Method) return NULL; } if (!java_lang_reflect_Method_method) { java_lang_reflect_Method_method = rvmGetInstanceField(env, java_lang_reflect_Method, "method", "J"); if (!java_lang_reflect_Method_method) return NULL; } return (Method*) LONG_TO_PTR(rvmGetLongInstanceFieldValue(env, methodObject, java_lang_reflect_Method_method)); }
Field* getFieldFromFieldObject(Env* env, Object* fieldObject) { if (!java_lang_reflect_Field) { java_lang_reflect_Field = rvmFindClassUsingLoader(env, "java/lang/reflect/Field", NULL); if (!java_lang_reflect_Field) return NULL; } if (!java_lang_reflect_Field_field) { java_lang_reflect_Field_field = rvmGetInstanceField(env, java_lang_reflect_Field, "field", "J"); if (!java_lang_reflect_Field_field) return NULL; } return (Field*) LONG_TO_PTR(rvmGetLongInstanceFieldValue(env, fieldObject, java_lang_reflect_Field_field)); }
Object* Java_java_lang_Class_getEnclosingMethod(Env* env, Class* thiz) { Method* method = rvmAttributeGetEnclosingMethod(env, thiz); if (!method || METHOD_IS_CONSTRUCTOR(method)) return NULL; Class* jlr_Method = rvmFindClassUsingLoader(env, "java/lang/reflect/Method", NULL); if (!jlr_Method) return NULL; Method* constructor = rvmGetInstanceMethod(env, jlr_Method, "<init>", "(J)V"); if (!constructor) return NULL; jvalue args[1]; args[0].j = PTR_TO_LONG(method); return rvmNewObjectA(env, jlr_Method, constructor, args); }
static jboolean getEnclosingMethodIterator(Env* env, char* className, char* methodName, char* methodDesc, void* data) { Method** result = (Method**) ((void**) data)[0]; Class* clazz = (Class*) ((void**) data)[1]; if (methodName && methodDesc) { Class* c = rvmFindClassUsingLoader(env, className, clazz->classLoader); if (c) { *result = rvmGetMethod(env, c, methodName, methodDesc); } return FALSE; // Stop iterating } return TRUE; // Continue with next attribute }
static void throwSocketExceptionErrno(Env* env, int errnum) { char message[512]; JClass* exCls = rvmFindClassUsingLoader(env, "java/net/SocketException", NULL); if (!exCls) { return; } if (strerror_r(errnum, message, 512) == 0) { rvmThrowNew(env, exCls, message); } else { rvmThrowNew(env, exCls, NULL); } }
static Class* ldcClass(Env* env, ClassInfoHeader* header) { Class* clazz = header->clazz; if (!clazz) { ClassLoader* loader = NULL; if (lookupClassInfo(env, header->className, _bcClassesHash) == header) { loader = systemClassLoader; } clazz = rvmFindClassUsingLoader(env, header->className, loader); if (!clazz) wrapClassNotFoundException(env, header->className); } return clazz; }
jboolean rvmInitAttributes(Env* env) { java_lang_TypeNotPresentException = rvmFindClassUsingLoader(env, "java/lang/TypeNotPresentException", NULL); if (!java_lang_TypeNotPresentException) return FALSE; java_lang_annotation_AnnotationFormatError = rvmFindClassUsingLoader(env, "java/lang/annotation/AnnotationFormatError", NULL); if (!java_lang_annotation_AnnotationFormatError) return FALSE; java_lang_reflect_Method = rvmFindClassUsingLoader(env, "java/lang/reflect/Method", NULL); if (!java_lang_reflect_Method) return FALSE; java_lang_reflect_Method_init = rvmGetInstanceMethod(env, java_lang_reflect_Method, "<init>", "(J)V"); if (!java_lang_reflect_Method_init) return FALSE; java_lang_annotation_Annotation = rvmFindClassUsingLoader(env, "java/lang/annotation/Annotation", NULL); if (!java_lang_annotation_Annotation) return FALSE; array_of_java_lang_annotation_Annotation = rvmFindClassUsingLoader(env, "[Ljava/lang/annotation/Annotation;", NULL); if (!array_of_java_lang_annotation_Annotation) return FALSE; Class* array_java_lang_Class = rvmFindClassUsingLoader(env, "[Ljava/lang/Class;", NULL); if (!array_java_lang_Class) return FALSE; emptyExceptionTypes = rvmNewObjectArray(env, 0, NULL, array_java_lang_Class, NULL); if (!emptyExceptionTypes) return FALSE; if (!rvmAddGlobalRef(env, (Object*) emptyExceptionTypes)) return FALSE; emptyAnnotations = rvmNewObjectArray(env, 0, NULL, array_of_java_lang_annotation_Annotation, NULL); if (!emptyAnnotations) return FALSE; if (!rvmAddGlobalRef(env, (Object*) emptyAnnotations)) return FALSE; return TRUE; }
static jboolean getDeclaredClassesIterator(Env* env, char* innerClass, char* outerClass, char* innerName, jint access, void* data) { ObjectArray* result = (ObjectArray*) ((void**) data)[0]; jint* index = (jint*) ((void**) data)[1]; Class* clazz = (Class*) ((void**) data)[2]; if (!outerClass || strcmp(outerClass, clazz->name)) { return TRUE; // Continue with next attribute } Class* c = rvmFindClassUsingLoader(env, innerClass, clazz->classLoader); if (!c) return FALSE; // Stop iterating result->values[*index] = (Object*) c; *index = *index + 1; return TRUE; // Continue with next attribute }
Object* createConstructorObject(Env* env, Method* method) { if (!java_lang_reflect_Constructor) { java_lang_reflect_Constructor = rvmFindClassUsingLoader(env, "java/lang/reflect/Constructor", NULL); if (!java_lang_reflect_Constructor) return NULL; } if (!java_lang_reflect_Constructor_init) { java_lang_reflect_Constructor_init = rvmGetInstanceMethod(env, java_lang_reflect_Constructor, "<init>", "(J)V"); if (!java_lang_reflect_Constructor_init) return NULL; } jvalue initArgs[1]; initArgs[0].j = PTR_TO_LONG(method); return rvmNewObjectA(env, java_lang_reflect_Constructor, java_lang_reflect_Constructor_init, initArgs); }
Object* createFieldObject(Env* env, Field* field) { if (!java_lang_reflect_Field) { java_lang_reflect_Field = rvmFindClassUsingLoader(env, "java/lang/reflect/Field", NULL); if (!java_lang_reflect_Field) return NULL; } if (!java_lang_reflect_Field_init) { java_lang_reflect_Field_init = rvmGetInstanceMethod(env, java_lang_reflect_Field, "<init>", "(J)V"); if (!java_lang_reflect_Field_init) return NULL; } jvalue initArgs[1]; initArgs[0].j = PTR_TO_LONG(field); return rvmNewObjectA(env, java_lang_reflect_Field, java_lang_reflect_Field_init, initArgs); }
jboolean rvmInitMemory(Env* env) { vm = env->vm; java_lang_ref_Reference = rvmFindClassUsingLoader(env, "java/lang/ref/Reference", NULL); if (!java_lang_ref_Reference) return FALSE; java_lang_ref_Reference_referent = rvmGetInstanceField(env, java_lang_ref_Reference, "referent", "Ljava/lang/Object;"); if (!java_lang_ref_Reference_referent) return FALSE; java_lang_ref_Reference_pendingNext = rvmGetInstanceField(env, java_lang_ref_Reference, "pendingNext", "Ljava/lang/ref/Reference;"); if (!java_lang_ref_Reference_pendingNext) return FALSE; java_lang_ref_Reference_queue = rvmGetInstanceField(env, java_lang_ref_Reference, "queue", "Ljava/lang/ref/ReferenceQueue;"); if (!java_lang_ref_Reference_queue) return FALSE; java_lang_ref_Reference_queueNext = rvmGetInstanceField(env, java_lang_ref_Reference, "queueNext", "Ljava/lang/ref/Reference;"); if (!java_lang_ref_Reference_queueNext) return FALSE; java_lang_ref_PhantomReference = rvmFindClassUsingLoader(env, "java/lang/ref/PhantomReference", NULL); if (!java_lang_ref_PhantomReference) return FALSE; java_lang_ref_WeakReference = rvmFindClassUsingLoader(env, "java/lang/ref/WeakReference", NULL); if (!java_lang_ref_WeakReference) return FALSE; java_lang_ref_SoftReference = rvmFindClassUsingLoader(env, "java/lang/ref/SoftReference", NULL); if (!java_lang_ref_SoftReference) return FALSE; java_lang_ref_FinalizerReference = rvmFindClassUsingLoader(env, "java/lang/ref/FinalizerReference", NULL); if (!java_lang_ref_FinalizerReference) return FALSE; java_lang_ref_FinalizerReference_add = rvmGetClassMethod(env, java_lang_ref_FinalizerReference, "add", "(Ljava/lang/Object;)V"); if (!java_lang_ref_FinalizerReference_add) return FALSE; java_lang_ref_FinalizerReference_zombie = rvmGetInstanceField(env, java_lang_ref_FinalizerReference, "zombie", "Ljava/lang/Object;"); if (!java_lang_ref_FinalizerReference_zombie) return FALSE; java_lang_ref_ReferenceQueue = rvmFindClassUsingLoader(env, "java/lang/ref/ReferenceQueue", NULL); if (!java_lang_ref_ReferenceQueue) return FALSE; java_lang_ref_ReferenceQueue_add = rvmGetClassMethod(env, java_lang_ref_ReferenceQueue, "add", "(Ljava/lang/ref/Reference;)V"); if (!java_lang_ref_ReferenceQueue_add) return FALSE; java_nio_ReadWriteDirectByteBuffer = rvmFindClassUsingLoader(env, "java/nio/ReadWriteDirectByteBuffer", NULL); if (!java_nio_ReadWriteDirectByteBuffer) return FALSE; java_nio_ReadWriteDirectByteBuffer_init = rvmGetInstanceMethod(env, java_nio_ReadWriteDirectByteBuffer, "<init>", "(II)V"); if (!java_nio_ReadWriteDirectByteBuffer_init) return FALSE; Class* java_nio_Buffer = rvmFindClassUsingLoader(env, "java/nio/Buffer", NULL); if (!java_nio_Buffer) return FALSE; java_nio_Buffer_effectiveDirectAddress = rvmGetInstanceField(env, java_nio_Buffer, "effectiveDirectAddress", "I"); if (!java_nio_Buffer_effectiveDirectAddress) return FALSE; java_nio_Buffer_capacity = rvmGetInstanceField(env, java_nio_Buffer, "capacity", "I"); if (!java_nio_Buffer_capacity) return FALSE; // Make sure that java.lang.ReferenceQueue is initialized now to prevent deadlocks during finalization // when both holding the referentsLock and the classLock. rvmInitialize(env, java_lang_ref_ReferenceQueue); if (rvmExceptionOccurred(env)) return FALSE; return TRUE; }
void throwInvocationTargetException(Env* env, Object* throwable) { rvmExceptionClear(env); if (!java_lang_reflect_InvocationTargetException) { java_lang_reflect_InvocationTargetException = rvmFindClassUsingLoader(env, "java/lang/reflect/InvocationTargetException", NULL); if (!java_lang_reflect_InvocationTargetException) return; } if (!java_lang_reflect_InvocationTargetException_init) { java_lang_reflect_InvocationTargetException_init = rvmGetMethod(env, java_lang_reflect_InvocationTargetException, "<init>", "(Ljava/lang/Throwable;)V"); if (!java_lang_reflect_InvocationTargetException_init) return; } jvalue initArgs[1]; initArgs[0].l = (jobject) throwable; Object* exception = rvmNewObjectA(env, java_lang_reflect_InvocationTargetException, java_lang_reflect_InvocationTargetException_init, initArgs); if (!exception) return; rvmThrow(env, exception); }
Class* findClassAt(Env* env, void* pc) { AddressClassLookup* lookups = getAddressClassLookups(env); if (!lookups) return NULL; AddressClassLookup needle = {NULL, pc, pc}; AddressClassLookup* result = bsearch(&needle, lookups, addressClassLookupsCount, sizeof(AddressClassLookup), addressClassLookupCompareBSearch); if (!result) return NULL; ClassInfoHeader* header = result->classInfoHeader; Class* clazz = header->clazz; if (!clazz) { ClassLoader* loader = NULL; if (lookupClassInfo(env, header->className, _bcClassesHash) == header) { loader = systemClassLoader; } clazz = rvmFindClassUsingLoader(env, header->className, loader); } return clazz; }
static void loadInterfaces(Env* env, Class* clazz) { ClassInfoHeader* header = lookupClassInfo(env, clazz->name, !clazz->classLoader || !clazz->classLoader->parent ? _bcBootClassesHash : _bcClassesHash); if (!header) return; ClassInfo ci; jint i; void* p = header; readClassInfo(&p, &ci); for (i = 0; i < ci.interfaceCount; i++) { const char* interfaceName = readInterfaceName(&p); Class* interface = rvmFindClassUsingLoader(env, interfaceName, clazz->classLoader); if (!interface) return; rvmAddInterface(env, clazz, interface); if (rvmExceptionCheck(env)) return; } }
static jboolean getExceptionsIterator(Env* env, jbyte type, void* attributes, void* data) { ObjectArray** result = (ObjectArray**) ((void**) data)[0]; Method* method = (Method*) ((void**) data)[1]; if (type == EXCEPTIONS) { jint length = getInt(&attributes); ObjectArray* array = rvmNewObjectArray(env, length, java_lang_Class, NULL, NULL); if (array) { jint i = 0; for (i = 0; i < length; i++) { char* className = getString(&attributes); Class* c = rvmFindClassUsingLoader(env, className, method->clazz->classLoader); if (!c) return FALSE; array->values[i] = (Object*) c; } *result = array; } return FALSE; // Stop iterating } return TRUE; // Continue with next attribute }
static Class* createClass(Env* env, ClassInfoHeader* header, ClassLoader* classLoader) { ClassInfo ci; void* p = header; readClassInfo(&p, &ci); Class* superclass = NULL; if (ci.superclassName) { superclass = rvmFindClassUsingLoader(env, ci.superclassName, classLoader); if (!superclass) return NULL; } Class* clazz = rvmAllocateClass(env, header->className, superclass, classLoader, ci.access, header->classDataSize, header->instanceDataSize, header->instanceDataOffset, header->classRefCount, header->instanceRefCount, ci.attributes, header->initializer); if (clazz) { if (!rvmRegisterClass(env, clazz)) return NULL; header->clazz = clazz; } return clazz; }
ObjectArray* Java_java_net_NetworkInterface_getInterfaceNames(Env* env, JClass* cls) { if (!java_lang_String_array) { java_lang_String_array = rvmFindClassUsingLoader(env, "[Ljava/lang/String;", NULL); if (!java_lang_String_array) { return NULL; } } struct if_nameindex* ifs = if_nameindex(); if (!ifs) { // Assume out of memory rvmThrowOutOfMemoryError(env); return NULL; } jint count = 0; while (ifs[count].if_index > 0) { count++; } ObjectArray* result = rvmNewObjectArray(env, count, NULL, java_lang_String_array, NULL); if (!result) { goto done; } jint i = 0; for (i = 0; i < count; i++) { Object* name = rvmNewStringUTF(env, ifs[i].if_name, -1); if (!name) { goto done; } result->values[i] = name; } done: if_freenameindex(ifs); return result; }