/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This file is part of SableVM. * * See the file "LICENSE" for Copyright information and the * * terms and conditions for copying, distribution and * * modification of SableVM. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "includes.h" JNIEXPORT jboolean JNICALL Java_java_lang_Class_isInitialized (JNIEnv *env, jobject this); JNIEXPORT void JNICALL Java_java_lang_Class_setInitialized (JNIEnv *env, jobject this); JNIEXPORT void JNICALL Java_java_lang_Class_step7 (JNIEnv *env, jobject this); JNIEXPORT void JNICALL Java_java_lang_Class_step8 (JNIEnv *env, jobject this); JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll (JNIEnv *env, jclass class, jobject o); JNIEXPORT void JNICALL Java_java_lang_VMSystem_arraycopy (JNIEnv *env, jclass class, jobject src, int srcStart, jobject dest, int destStart, int len); JNIEXPORT jobject JNICALL Java_java_lang_Class_nativeForName (JNIEnv *env, jclass class, jobject name); JNIEXPORT jstring JNICALL Java_java_lang_Runtime_getLibraryPath (JNIEnv *env, jclass class); JNIEXPORT jint JNICALL Java_java_lang_Runtime_nativeLoad (JNIEnv *env, jobject this, jstring filename); JNIEXPORT jobject JNICALL Java_java_lang_Throwable_internalFillInStackTrace (JNIEnv *env, jobject this); JNIEXPORT jobject JNICALL Java_java_lang_Class_nativeGetRealName (JNIEnv *env, jobject this); JNIEXPORT jobject JNICALL Java_java_lang_Class_nativeGetConstructor (JNIEnv *env, jobject this, jobject desc); JNIEXPORT jobject JNICALL Java_java_lang_reflect_Constructor_constructNative (JNIEnv *env, jobject this, jobjectArray args_array, jbyteArray svm_method); JNIEXPORT void JNICALL Java_org_sablevm_vm_Startup_main (JNIEnv *env, jclass class, jobject className, jobject args); JNIEXPORT jobject JNICALL Java_java_lang_Class_getClassLoader (JNIEnv *env, jobject this); JNIEXPORT void JNICALL Java_java_lang_Runtime_exitInternal (JNIEnv *env, jobject this, jint status); JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode (JNIEnv *env, jclass class, jobject o); JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone (JNIEnv *env, jclass class, jobject o); JNIEXPORT jobject JNICALL Java_java_lang_VMSystem_getUserDir (JNIEnv *env, jclass class); JNIEXPORT jint JNICALL Java_java_lang_VMSystem_getPropertiesCount (JNIEnv *env, jclass class); JNIEXPORT jobject JNICALL Java_java_lang_VMSystem_getProperty (JNIEnv *env, jclass class, jint n); JNIEXPORT jobject JNICALL Java_java_lang_VMSystem_getClassPath (JNIEnv *env, jclass class); JNIEXPORT jint JNICALL Java_java_lang_VMSystem_getPathCount (JNIEnv *env, jclass class); JNIEXPORT jobject JNICALL Java_java_lang_VMSystem_getPath (JNIEnv *env, jclass class, jint index); /* ---------------------------------------------------------------------- Java_java_lang_VMSystem_debug ---------------------------------------------------------------------- */ JNIEXPORT void JNICALL Java_java_lang_VMSystem_debug (JNIEnv *env, jclass class, jstring string); JNIEXPORT void JNICALL Java_java_lang_VMSystem_debug (JNIEnv *env, jclass class, jstring string) { jsize length, utflength; char *buf; length = (*env)->GetStringLength (env, string); utflength = (*env)->GetStringUTFLength (env, string); buf = _svmf_malloc (utflength + 1); (*env)->GetStringUTFRegion (env, string, (jsize) 0, length, buf); printf ("%s\n", buf); _svmf_free (buf); class = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_Class_nativeForName ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_Class_nativeForName (JNIEnv *env, jclass class, jobject name) { jsize length, utflength; char *buf; jobject result; length = (*env)->GetStringLength (env, name); utflength = (*env)->GetStringUTFLength (env, name); buf = _svmf_malloc (utflength + 1); (*env)->GetStringUTFRegion (env, name, (jsize) 0, length, buf); if ((*env)->ExceptionCheck (env)) { _svmf_free (buf); _svmdf_error_ClassNotFoundException ((_svmt_JNIEnv *) env); return NULL; } result = (*env)->FindClass (env, buf); _svmf_free (buf); return result; class = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_Runtime_getLibraryPath ---------------------------------------------------------------------- */ JNIEXPORT jstring JNICALL Java_java_lang_Runtime_getLibraryPath (JNIEnv *_env, jclass class) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; _svmt_JavaVM *vm = env->vm; return (*_env)->NewStringUTF (_env, vm->boot_loader.boot_library_path); class = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_Runtime_nativeLoad ---------------------------------------------------------------------- */ JNIEXPORT jint JNICALL Java_java_lang_Runtime_nativeLoad (JNIEnv *_env, jobject this, jstring filename) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; _svmt_class_loader_info *class_loader = env->vm->boot_loader.class_loader_info; jsize length, utflength; char *buf; _svmt_native_libraries_list *node; length = (*_env)->GetStringLength (_env, filename); utflength = (*_env)->GetStringUTFLength (_env, filename); if (_svmdf_clmalloc_chars (env, class_loader, utflength + 1, &buf) != JNI_OK) { _svmdf_error_OutOfMemoryError (env); return 0; } if (_svmdf_clzalloc_native_libraries_list (env, class_loader, &node) != JNI_OK) { _svmdf_error_OutOfMemoryError (env); return 0; } (*_env)->GetStringUTFRegion (_env, filename, (jsize) 0, length, buf); if ((*_env)->ExceptionCheck (_env) == JNI_TRUE) { return 0; } { void *lib = dlopen (buf, RTLD_LAZY); if (lib == NULL) { return 0; } node->name = buf; node->handle = lib; *(class_loader->tail) = node; class_loader->tail = &node->next; } return 1; this = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_Throwable_fillInStackTrace ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_Throwable_internalFillInStackTrace (JNIEnv *_env, jobject this) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; _svmt_JavaVM *vm = env->vm; size_t frame_offset = ((char *) env->stack.current_frame) - ((char *) env->stack.start); _svmt_stack_frame *frame; jobject stacktrace = _svmf_new_native_global (vm); if (stacktrace == NULL) { _svmdf_error_OutOfMemoryError (env); return NULL; } *stacktrace = _svmf_new_object_instance (env, vm->boot_loader.classes.stacktrace); if (*stacktrace == NULL) { _svmf_free_native_global (vm, stacktrace); return NULL; } if (_svmdf_invoke_init (env, vm->boot_loader.methods.stacktrace_init, stacktrace) != JNI_OK) { _svmf_free_native_global (vm, stacktrace); return NULL; } frame = (_svmt_stack_frame *) (((char *) env->stack.start) + frame_offset); while (1) { _svmt_method_info *method; _svmt_stack_value *locals; if (frame->previous_offset == 0) { goto end; } frame = (_svmt_stack_frame *) (((char *) frame) - frame->previous_offset); frame_offset = ((char *) frame) - ((char *) env->stack.start); method = frame->method; if (IS_SET (method->access_flags, SVM_ACC_DUMMY) || IS_SET (method->access_flags, SVM_ACC_NATIVE) || (method->locals_size == 0)) { break; } locals = (_svmt_stack_value *) (((char *) frame) - method->locals_size); if (locals[0].reference != *this) { break; } } while (1) { _svmt_method_info *method = frame->method; if (IS_SET (method->access_flags, SVM_ACC_DUMMY)) { } else if (IS_SET (method->access_flags, SVM_ACC_NATIVE) || (method->code != method->code_attribute->prepared_code)) { jobject className = _svmf_get_string (env, method->class_info->name); jobject methodName = _svmf_get_string (env, DREF (method->name, value)); jobject methodDescriptor = _svmf_get_string (env, DREF (method->descriptor, value)); if (className == NULL || methodName == NULL || methodDescriptor == NULL) { if (className != NULL) { _svmf_free_native_global (vm, className); } if (methodName != NULL) { _svmf_free_native_global (vm, methodName); } if (methodDescriptor != NULL) { _svmf_free_native_global (vm, methodDescriptor); } _svmf_free_native_global (vm, stacktrace); return NULL; } if (_svmdf_invoke_stacktrace_addframe (env, vm->boot_loader.methods.stacktrace_addframe, stacktrace, className, methodName, methodDescriptor, NULL, 0) != JNI_OK) { _svmf_free_native_global (vm, className); _svmf_free_native_global (vm, methodName); _svmf_free_native_global (vm, methodDescriptor); _svmf_free_native_global (vm, stacktrace); return NULL; } _svmf_free_native_global (vm, className); _svmf_free_native_global (vm, methodName); _svmf_free_native_global (vm, methodDescriptor); } else { _svmt_bytecode_info *bc_info = method->code_attribute->bc_info; jint attributes_count = method->code_attribute->attributes_count; jint i; _svmt_LineNumberTable_attribute *lnattribute = NULL; _svmt_SourceFile_attribute *sfattribute = NULL; size_t offset = frame->pc - method->code; jint table_length; _svmt_line_number_table *table; jint lineNumber = -1; for (i = 0; i < attributes_count; i++) { if (strcmp (DREF (method->code_attribute->attributes[i]->name, value), "LineNumberTable") == 0) { lnattribute = (_svmt_LineNumberTable_attribute *) method->code_attribute->attributes[i]; } } if (lnattribute != NULL) { table_length = lnattribute->line_number_table_length; table = lnattribute->line_number_table; for (i = table_length - 1; i >= 0; i--) { if (offset >= bc_info[table[i].start_pc].code_offset + bc_info[table[i].start_pc].code_length) { lineNumber = table[i].line_number; break; } } } attributes_count = method->class_info->attributes_count; for (i = 0; i < attributes_count; i++) { if (strcmp (DREF (method->class_info->attributes[i]->name, value), "SourceFile") == 0) { sfattribute = (_svmt_SourceFile_attribute *) method->class_info->attributes[i]; } } if (sfattribute == NULL || lineNumber == -1) { jobject className = _svmf_get_string (env, method->class_info->name); jobject methodName = _svmf_get_string (env, DREF (method->name, value)); jobject methodDescriptor = _svmf_get_string (env, DREF (method->descriptor, value)); if (className == NULL || methodName == NULL || methodDescriptor == NULL) { if (className != NULL) { _svmf_free_native_global (vm, className); } if (methodName != NULL) { _svmf_free_native_global (vm, methodName); } if (methodDescriptor != NULL) { _svmf_free_native_global (vm, methodDescriptor); } _svmf_free_native_global (vm, stacktrace); return NULL; } if (_svmdf_invoke_stacktrace_addframe (env, vm->boot_loader.methods.stacktrace_addframe, stacktrace, className, methodName, methodDescriptor, NULL, 0) != JNI_OK) { _svmf_free_native_global (vm, className); _svmf_free_native_global (vm, methodName); _svmf_free_native_global (vm, methodDescriptor); _svmf_free_native_global (vm, stacktrace); return NULL; } _svmf_free_native_global (vm, className); _svmf_free_native_global (vm, methodName); _svmf_free_native_global (vm, methodDescriptor); } else { jobject className = _svmf_get_string (env, method->class_info->name); jobject methodName = _svmf_get_string (env, DREF (method->name, value)); jobject methodDescriptor = _svmf_get_string (env, DREF (method->descriptor, value)); jobject fileName = _svmf_get_string (env, DREF (sfattribute->sourcefile, value)); if (className == NULL || methodName == NULL || methodDescriptor == NULL || fileName == NULL) { if (className != NULL) { _svmf_free_native_global (vm, className); } if (methodName != NULL) { _svmf_free_native_global (vm, methodName); } if (methodDescriptor != NULL) { _svmf_free_native_global (vm, methodDescriptor); } if (fileName != NULL) { _svmf_free_native_global (vm, fileName); } _svmf_free_native_global (vm, stacktrace); return NULL; } if (_svmdf_invoke_stacktrace_addframe (env, vm->boot_loader.methods.stacktrace_addframe, stacktrace, className, methodName, methodDescriptor, fileName, lineNumber) != JNI_OK) { _svmf_free_native_global (vm, className); _svmf_free_native_global (vm, methodName); _svmf_free_native_global (vm, methodDescriptor); _svmf_free_native_global (vm, fileName); _svmf_free_native_global (vm, stacktrace); return NULL; } _svmf_free_native_global (vm, className); _svmf_free_native_global (vm, methodName); _svmf_free_native_global (vm, methodDescriptor); _svmf_free_native_global (vm, fileName); } } frame = (_svmt_stack_frame *) (((char *) env->stack.start) + frame_offset); if (frame->previous_offset == 0) { goto end; } frame = (_svmt_stack_frame *) (((char *) frame) - frame->previous_offset); frame_offset = ((char *) frame) - ((char *) env->stack.start); } end: { jobject result = (*_env)->CallObjectMethod (_env, stacktrace, vm->boot_loader.methods.stacktrace_tostring); _svmf_free_native_global (vm, stacktrace); return result; } } /* ---------------------------------------------------------------------- Java_java_lang_Class_nativeGetRealName ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_Class_nativeGetRealName (JNIEnv *_env, jobject this) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; _svmt_array_instance *data = GET_ARRAY_REFERENCE_FIELD (*this, env->vm->boot_loader.fields.jlclass_data->offset); _svmt_type_info *ti = *((_svmt_type_info **) &ARRAY_BYTE_ELEMENT (data, 0)); return (*_env)->NewStringUTF (_env, ti->name); } /* ---------------------------------------------------------------------- Java_java_lang_Class_nativeGetConstructor ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_Class_nativeGetConstructor (JNIEnv *env, jobject this, jobject desc) { jsize length, utflength; char *buf; length = (*env)->GetStringLength (env, desc); utflength = (*env)->GetStringUTFLength (env, desc); buf = _svmf_malloc (utflength + 1); (*env)->GetStringUTFRegion (env, desc, (jsize) 0, length, buf); { jmethodID constructor = (*env)->GetMethodID (env, this, "", buf); jobject cls = (*env)->FindClass (env, "java/lang/reflect/Constructor"); jmethodID methodID = (*env)->GetMethodID (env, cls, "", "([B)V"); jbyteArray ba = (*env)->NewByteArray (env, sizeof (jmethodID)); *((jmethodID *) &ARRAY_BYTE_ELEMENT (*ba, 0)) = constructor; _svmf_free (buf); return (*env)->NewObject (env, cls, methodID, ba); } } /* ---------------------------------------------------------------------- Java_java_lang_Class_nativeGetConstructor ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_reflect_Constructor_constructNative (JNIEnv *env, jobject this, jobjectArray args_array, jbyteArray svm_method) { jmethodID methodID = *((_svmt_method_info **) &ARRAY_BYTE_ELEMENT (*svm_method, 0)); jvalue *args = NULL; jint i; jsize length = (*env)->GetArrayLength (env, args_array); jobject result; if (length > 0) { args = _svmf_malloc (sizeof (jvalue) * length); } for (i = 0; i < length; i++) { args[i].l = (*env)->GetObjectArrayElement (env, args_array, i); } result = (*env)->NewObjectA (env, methodID->class_info->class_instance, methodID, args); _svmf_free (args); return result; this = NULL; } /* ---------------------------------------------------------------------- Java_org_sablevm_vm_Startup_main ---------------------------------------------------------------------- */ JNIEXPORT void JNICALL Java_org_sablevm_vm_Startup_main (JNIEnv *env, jclass cls, jobject className, jobject args) { jsize length, utflength; char *buf; jclass class; jmethodID methodID; length = (*env)->GetStringLength (env, className); utflength = (*env)->GetStringUTFLength (env, className); buf = _svmf_malloc (utflength + 1); (*env)->GetStringUTFRegion (env, className, (jsize) 0, length, buf); class = (*env)->FindClass (env, buf); _svmf_free (buf); methodID = (*env)->GetStaticMethodID (env, class, "main", "([Ljava/lang/String;)V"); (*env)->CallStaticVoidMethod (env, class, methodID, args); cls = NULL; } /* ---------------------------------------------------------------------- Java_org_sablevm_vm_Startup_main ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_Class_getClassLoader (JNIEnv *_env, jobject this) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; _svmt_array_instance *data = GET_ARRAY_REFERENCE_FIELD (*this, env->vm->boot_loader.fields.jlclass_data->offset); _svmt_type_info *ti = *((_svmt_type_info **) &ARRAY_BYTE_ELEMENT (data, 0)); return ti->class_loader_info->class_loader; } /* ---------------------------------------------------------------------- Java_java_lang_Runtime_exitInternal ---------------------------------------------------------------------- */ JNIEXPORT void JNICALL Java_java_lang_Runtime_exitInternal (JNIEnv *_env, jobject this, jint status) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; env->vm->exit (status); this = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_VMSystem_identityHashCode ---------------------------------------------------------------------- */ JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode (JNIEnv *_env, jclass class, jobject o) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; return _svmf_get_hashcode (env, *o); class = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_VMObject_clone ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone (JNIEnv *_env, jclass class, jobject o) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; void *word; word = (*o)->lockword; if (_svmm_lockw_is_array (word)) { _svmt_array_instance header = *((_svmt_array_instance *) *o); _svmt_array_instance *clone = _svmf_new_array_instance (env, (_svmt_array_info *) ((*o)->vtable->type), header.size); size_t next_offset = ARRAY_HEADER_SIZE; size_t start_offset = 0; size_t instance_size; jint size = header.size; if (clone == NULL) { return NULL; } switch (_svmm_lockw_type (word)) { case SVM_TYPE_BOOLEAN: { next_offset += (((size_t) size) + 7) / 8; } break; case SVM_TYPE_BYTE: { next_offset += ((size_t) size); } break; case SVM_TYPE_SHORT: { next_offset += ((size_t) size) * 2; } break; case SVM_TYPE_CHAR: { next_offset += ((size_t) size) * 2; } break; case SVM_TYPE_INT: { next_offset += ((size_t) size) * 4; } break; case SVM_TYPE_LONG: { next_offset += ((size_t) size) * 8; } break; case SVM_TYPE_FLOAT: { next_offset += ((size_t) size) * 4; } break; case SVM_TYPE_DOUBLE: { next_offset += ((size_t) size) * 8; } break; case SVM_TYPE_REFERENCE: { start_offset += ((size_t) size) * sizeof (void *); } break; default: { abort (); } break; } next_offset = ALIGNED_SIZE (next_offset); start_offset = ALIGNED_SIZE (start_offset); instance_size = start_offset + next_offset; header = *clone; memcpy (((char *) clone) - start_offset, ((char *) *o) - start_offset, instance_size); *clone = header; return (*_env)->NewLocalRef (_env, (jobject) &clone); } { _svmt_object_instance header = *((_svmt_object_instance *) *o); _svmt_object_instance *clone = _svmf_new_object_instance (env, (_svmt_class_info *) ((*o)->vtable->type)); size_t end = _svmm_lockw_end (word); size_t start = _svmm_lockw_start (word); size_t next_offset = end * SVM_ALIGNMENT; size_t start_offset = start * SVM_ALIGNMENT; size_t instance_size; if (end == SVM_LOCKW_OVRFLW) { next_offset = ((_svmt_object_instance *) *o)->vtable->next_offset; } if (start == SVM_LOCKW_OVRFLW) { start_offset = ((_svmt_object_instance *) *o)->vtable->start_offset; } instance_size = start_offset + next_offset; header = *clone; memcpy (((char *) clone) - start_offset, ((char *) *o) - start_offset, instance_size); *clone = header; return (*_env)->NewLocalRef (_env, (jobject) &clone); } class = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_VMSystem_getUserDir ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_VMSystem_getUserDir (JNIEnv *_env, jclass class) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; char *str = _svmf_current_working_directory (); if (str == NULL) { _svmdf_error_OutOfMemoryError (env); return NULL; } { jobject obj = _svmf_get_string (env, str); jobject result = (*_env)->NewLocalRef (_env, obj); _svmf_free_native_global (env->vm, obj); _svmf_free (str); return result; } class = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_VMSystem_getClassPath ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_VMSystem_getClassPath (JNIEnv *_env, jclass class) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; char *str = env->vm->boot_loader.classpath; printf ("PATH = %s\n", str); if (str == NULL) { return NULL; } { jobject obj = _svmf_get_string (env, str); jobject result = (*_env)->NewLocalRef (_env, obj); _svmf_free_native_global (env->vm, obj); return result; } class = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_VMSystem_getPropertiesCount ---------------------------------------------------------------------- */ JNIEXPORT jint JNICALL Java_java_lang_VMSystem_getPropertiesCount (JNIEnv *_env, jclass class) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; jint i, count = 0; JavaVMInitArgs *vm_args = env->vm->initialization->vm_args; for (i = 0; i < vm_args->nOptions; i++) { if (vm_args->options[i].optionString[0] == '-' && vm_args->options[i].optionString[1] == 'D') { count++; } } return count; class = NULL; } /* ---------------------------------------------------------------------- Java_java_lang_VMSystem_getProperty ---------------------------------------------------------------------- */ JNIEXPORT jobject JNICALL Java_java_lang_VMSystem_getProperty (JNIEnv *_env, jclass class, jint n) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; jint i, count = -1; JavaVMInitArgs *vm_args = env->vm->initialization->vm_args; for (i = 0; i < vm_args->nOptions; i++) { if (vm_args->options[i].optionString[0] == '-' && vm_args->options[i].optionString[1] == 'D') { count++; } if (count == n) { jobject obj = _svmf_get_string (env, &vm_args->options[i].optionString[2]); jobject result = (*_env)->NewLocalRef (_env, obj); _svmf_free_native_global (env->vm, obj); return result; } } abort (); return NULL; class = NULL; } JNIEXPORT jint JNICALL Java_java_lang_VMSystem_getPathCount (JNIEnv *_env, jclass class) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; _svmt_JavaVM *vm = env->vm; return vm->boot_loader.path_count; class = NULL; } JNIEXPORT jobject JNICALL Java_java_lang_VMSystem_getPath (JNIEnv *_env, jclass class, jint index) { _svmt_JNIEnv *env = (_svmt_JNIEnv *) _env; char *str = env->vm->boot_loader.class_paths[index]; if (str == NULL) { return NULL; } { jobject obj = _svmf_get_string (env, str); jobject result = (*_env)->NewLocalRef (_env, obj); _svmf_free_native_global (env->vm, obj); return result; } class = NULL; }