//===- ClasspathReflect.cpp - Internal representation of core system classes -// // // The VMKit project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "types.h" #include "Classpath.h" #include "ClasspathReflect.h" #include "JavaArray.h" #include "JavaClass.h" #include "JavaObject.h" #include "JavaTypes.h" #include "JavaThread.h" #include "JavaUpcalls.h" #include "Jnjvm.h" #include "JnjvmClassLoader.h" using namespace j3; extern "C" { JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_VMMethod_getDefaultValue( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectVMMethod* VMMeth) { JavaObject* res = 0; JavaObject* methodType; llvm_gcroot(VMMeth, 0); llvm_gcroot(res, 0); llvm_gcroot(methodType, 0); BEGIN_NATIVE_EXCEPTION(0) dprintf("*************VMMethod_getDefaultValue*************\n"); Classpath* upcalls = JavaThread::get()->getJVM()->upcalls; UserClass* cl = JavaObjectVMMethod::getClass(VMMeth); dprintf("JavaClass:%s\n", UTF8Buffer(cl->name).cString()); // Annotation interface class. const UTF8* name = upcalls->newAnnotation->name; if (cl->inheritName(name->elements, name->size)) { // Find "default attribute" JavaMethod* method = JavaObjectVMMethod::getInternalMethod(VMMeth); JavaAttribute* annotationsAtt = method->lookupAttribute(JavaAttribute::annotationDefaultAttribute); dprintf("JavaMethod:%s\n", UTF8Buffer(method->name).cString()); if (annotationsAtt) { Reader reader(annotationsAtt, cl->bytes); AnnotationReader AR(reader, cl); methodType = method->getReturnType(cl->classLoader); res = AR.createElementValue(true, methodType, method->name); } } END_NATIVE_EXCEPTION return res; } JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_VMMethod_getAnnotation( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectVMMethod* VMMeth, JavaObjectClass* annotationClass) { JavaObject* res = 0; JavaObject* newHashMap = 0; llvm_gcroot(res, 0); llvm_gcroot(newHashMap, 0); llvm_gcroot(VMMeth, 0); llvm_gcroot(annotationClass, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); Classpath* upcalls = vm->upcalls; dprintf("*************VMMethod_getAnnotation*************\n"); if (annotationClass) { /* Retrieving annotationClass classname */ UserClass* clazz = JavaObjectClass::getClass(annotationClass)->asClass(); dprintf("searched annotation:%s\n\n", UTF8Buffer(clazz->name).cString()); /* Retrieving VMMethod.class attributes list */ UserClass* compilingClass = JavaObjectVMMethod::getClass(VMMeth); JavaMethod* method = JavaObjectVMMethod::getInternalMethod(VMMeth); JavaAttribute* annotationsAtt = method->lookupAttribute(JavaAttribute::annotationsAttribute); dprintf("JavaMethod:%s\n", UTF8Buffer(method->name).cString()); if (annotationsAtt) { Reader reader(annotationsAtt, compilingClass->bytes); AnnotationReader AR(reader, compilingClass); uint16 numAnnotations = reader.readU2(); for (uint16 i = 0; i < numAnnotations; ++i) { uint16 typeIndex = reader.readU2(); const UTF8* annoType = compilingClass->ctpInfo->UTF8At(typeIndex); // Remove the L and ; in the name annotation type (L.....;) // for the comparison. if (clazz->name->equals(annoType->elements+1, annoType->size-2)) { newHashMap = AR.createAnnotationMapValues(annotationClass); break; } else { AR.readAnnotationElementValues(); } } // end for if (newHashMap) { dprintf("Annotation creation\n"); res = upcalls->createAnnotation->invokeJavaObjectStatic(vm, upcalls->newAnnotationHandler, &annotationClass, &newHashMap); } } } else { vm->nullPointerException(); } END_NATIVE_EXCEPTION return res; } JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_VMMethod_getDeclaredAnnotations( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectVMMethod* VMMethod) { ArrayObject* arrayRes = 0; JavaObject* res = 0; JavaObject* annon = 0; JavaObject* newHashMap = 0; JavaObject* annotationClass = 0; llvm_gcroot(res, 0); llvm_gcroot(annon, 0); llvm_gcroot(newHashMap, 0); llvm_gcroot(VMMethod, 0); llvm_gcroot(annotationClass, 0); llvm_gcroot(arrayRes, 0); BEGIN_NATIVE_EXCEPTION(0) Jnjvm* vm = JavaThread::get()->getJVM(); Classpath* upcalls = vm->upcalls; /* Retrieving VMMethod.class attributes list */ UserClass* compilingClass = JavaObjectVMMethod::getClass(VMMethod); JavaMethod* method = JavaObjectVMMethod::getInternalMethod(VMMethod); JavaAttribute* annotationsAtt = method->lookupAttribute(JavaAttribute::annotationsAttribute); dprintf("JavaMethod : %s\n", UTF8Buffer(method->name).cString()); JnjvmClassLoader* loader = compilingClass->classLoader; if (annotationsAtt) { Reader reader(annotationsAtt, compilingClass->bytes); AnnotationReader AR(reader, compilingClass); uint16 numAnnotations = reader.readU2(); UserClassArray* array = upcalls->constructorArrayAnnotation; arrayRes = (ArrayObject *)(res = array->doNew(numAnnotations, vm)); for (uint16 i = 0; i < numAnnotations; ++i) { uint16 typeIndex = reader.readU2(); const UTF8* annoType = compilingClass->ctpInfo->UTF8At(typeIndex); annoType = annoType->extract(loader->hashUTF8, 1,annoType->size-1); dprintf("Annotation type : %s\n", UTF8Buffer(annoType).cString()); UserClass* AnnonClass = 0; UserCommonClass* commClass = loader->lookupClass(annoType); if (commClass) AnnonClass = commClass -> asClass(); else AnnonClass = loader->loadName(annoType, true, true, NULL); assert(AnnonClass && "Panic, imposible conditions"); dprintf("Loaded class : %s \n", UTF8Buffer(AnnonClass->name).cString()); annotationClass = AnnonClass->getClassDelegatee(vm); newHashMap = AR.createAnnotationMapValues(annotationClass); annon = upcalls->createAnnotation->invokeJavaObjectStatic(vm, upcalls->newAnnotationHandler, &annotationClass, &newHashMap); ArrayObject::setElement(arrayRes, annon, i); } // end for } else { UserClassArray* array = upcalls->constructorArrayAnnotation; res = array->doNew(0, vm); } END_NATIVE_EXCEPTION return res; } JNIEXPORT jint JNICALL Java_java_lang_reflect_VMMethod_getModifiersInternal( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectVMMethod* Meth) { jint res = 0; llvm_gcroot(Meth, 0); BEGIN_NATIVE_EXCEPTION(0) JavaMethod* meth = JavaObjectVMMethod::getInternalMethod(Meth); res = meth->access; END_NATIVE_EXCEPTION return res; } JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_VMMethod_getReturnType( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectVMMethod* Meth) { JavaObject* res = 0; llvm_gcroot(Meth, 0); llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) verifyNull(Meth); JavaMethod* meth = JavaObjectVMMethod::getInternalMethod(Meth); UserCommonClass* cls = (UserCommonClass*)JavaObjectVMMethod::getClass(Meth); JnjvmClassLoader* loader = cls->classLoader; res = meth->getReturnType(loader); END_NATIVE_EXCEPTION return res; } JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_VMMethod_getParameterTypes( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectVMMethod* Meth) { JavaObject* res = 0; llvm_gcroot(Meth, 0); llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) verifyNull(Meth); JavaMethod* meth = JavaObjectVMMethod::getInternalMethod(Meth); UserCommonClass* cls = (UserCommonClass*)JavaObjectVMMethod::getClass(Meth); JnjvmClassLoader* loader = cls->classLoader; res = meth->getParameterTypes(loader); END_NATIVE_EXCEPTION return res; } JavaObject* proceedVMMethod(JavaObjectVMMethod* Meth, JavaObject* obj, ArrayObject* args) __attribute__((noinline)); JavaObject* proceedVMMethod(JavaObjectVMMethod* Meth, JavaObject* obj, ArrayObject* args) { JavaObject* res = 0; JavaObject* exc = 0; llvm_gcroot(res, 0); llvm_gcroot(Meth, 0); llvm_gcroot(obj, 0); llvm_gcroot(args, 0); llvm_gcroot(exc, 0); Jnjvm* vm = JavaThread::get()->getJVM(); JavaMethod* meth = JavaObjectVMMethod::getInternalMethod(Meth); UserCommonClass* _cl = (UserCommonClass*)JavaObjectVMMethod::getClass(Meth); sint32 nbArgs = args ? ArrayObject::getSize(args) : 0; Signdef* sign = meth->getSignature(); sint32 size = sign->nbArguments; vmkit::ThreadAllocator allocator; jvalue* buf = size ? (jvalue*)allocator.Allocate(size * sizeof(jvalue)) : NULL; if (nbArgs == size) { //UserCommonClass* _cl = UserCommonClass::resolvedImplClass(vm, Cl, false); UserClass* cl = (UserClass*)_cl; if (isVirtual(meth->access)) { verifyNull(obj); UserCommonClass* objCl = JavaObject::getClass(obj); if (!(objCl->isSubclassOf(cl))) { vm->illegalArgumentException(" is not a valid type"); } // If the given method is not implemented in the given class (e.g. a method // declared in an interface, or declared abstract) then look for an implementation // of it in the class of the given "this" object. if (isInterface(cl->access) || isAbstract(meth->access)) { cl->initialiseClass(vm); UserClass* methodCl = 0; UserClass* lookup = objCl->isArray() ? objCl->super : objCl->asClass(); meth = lookup->lookupMethod(meth->name, meth->type, false, true, &methodCl); } } else { cl->initialiseClass(vm); } JavaObject** ptr = ArrayObject::getElements(args); Typedef* const* arguments = sign->getArgumentsType(); for (sint32 i = 0; i < size; ++i) { JavaObject::decapsulePrimitive(ptr[i], vm, &buf[i], arguments[i]); if (!arguments[i]->isPrimitive()) { buf[i].l = reinterpret_cast(&ptr[i]); } } JavaThread* th = JavaThread::get(); #define RUN_METH(TYPE, VAR) \ TRY { \ if (isVirtual(meth->access)) { \ if (isPublic(meth->access) && !isFinal(meth->access) && \ !isFinal(meth->classDef->access)) { \ VAR = meth->invoke##TYPE##VirtualBuf(vm, cl, obj, buf); \ } else { \ VAR = meth->invoke##TYPE##SpecialBuf(vm, cl, obj, buf); \ } \ } else { \ VAR = meth->invoke##TYPE##StaticBuf(vm, cl, buf); \ } \ } CATCH { \ exc = th->getJavaException(); \ } END_CATCH; \ if (exc) { \ th->clearException(); \ th->getJVM()->invocationTargetException(exc); \ return NULL; \ } Typedef* retType = sign->getReturnType(); if (retType->isPrimitive()) { PrimitiveTypedef* prim = (PrimitiveTypedef*)retType; if (prim->isVoid()) { res = 0; uint32 val = 0; RUN_METH(Int, val); } else if (prim->isBool()) { uint32 val = 0; RUN_METH(Int, val); res = vm->upcalls->boolClass->doNew(vm); vm->upcalls->boolValue->setInstanceInt8Field(res, val); } else if (prim->isByte()) { uint32 val = 0; RUN_METH(Int, val); res = vm->upcalls->byteClass->doNew(vm); vm->upcalls->byteValue->setInstanceInt8Field(res, val); } else if (prim->isChar()) { uint32 val = 0; RUN_METH(Int, val); res = vm->upcalls->charClass->doNew(vm); vm->upcalls->charValue->setInstanceInt16Field(res, val); } else if (prim->isShort()) { uint32 val = 0; RUN_METH(Int, val); res = vm->upcalls->shortClass->doNew(vm); vm->upcalls->shortValue->setInstanceInt16Field(res, val); } else if (prim->isInt()) { uint32 val = 0; RUN_METH(Int, val); res = vm->upcalls->intClass->doNew(vm); vm->upcalls->intValue->setInstanceInt32Field(res, val); } else if (prim->isLong()) { sint64 val = 0; RUN_METH(Long, val); res = vm->upcalls->longClass->doNew(vm); vm->upcalls->longValue->setInstanceLongField(res, val); } else if (prim->isFloat()) { float val = 0; RUN_METH(Float, val); res = vm->upcalls->floatClass->doNew(vm); vm->upcalls->floatValue->setInstanceFloatField(res, val); } else if (prim->isDouble()) { double val = 0; RUN_METH(Double, val); res = vm->upcalls->doubleClass->doNew(vm); vm->upcalls->doubleValue->setInstanceDoubleField(res, val); } } else { RUN_METH(JavaObject, res); } } else { vm->illegalArgumentException("wrong number of arguments"); return NULL; } return res; } #undef RUN_METH JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_VMMethod_invoke( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectVMMethod* Meth, JavaObject* obj, ArrayObject* args) { JavaObject* res = 0; llvm_gcroot(res, 0); llvm_gcroot(Meth, 0); llvm_gcroot(obj, 0); llvm_gcroot(args, 0); BEGIN_NATIVE_EXCEPTION(0) verifyNull(Meth); res = proceedVMMethod(Meth, obj, args); END_NATIVE_EXCEPTION return res; } JNIEXPORT ArrayObject* JNICALL Java_java_lang_reflect_VMMethod_getExceptionTypes( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectVMMethod* Meth) { ArrayObject* res = 0; llvm_gcroot(Meth, 0); llvm_gcroot(res, 0); BEGIN_NATIVE_EXCEPTION(0) verifyNull(Meth); JavaMethod* meth = JavaObjectVMMethod::getInternalMethod(Meth); UserCommonClass* cls = (UserCommonClass*)JavaObjectVMMethod::getClass(Meth); JnjvmClassLoader* loader = cls->classLoader; res = meth->getExceptionTypes(loader); END_NATIVE_EXCEPTION return res; } JNIEXPORT JavaObject* JNICALL Java_java_lang_reflect_VMMethod_getSignature( #ifdef NATIVE_JNI JNIEnv *env, #endif JavaObjectVMMethod* Meth) { JavaObject* result = 0; llvm_gcroot(Meth, 0); llvm_gcroot(result, 0); BEGIN_NATIVE_EXCEPTION(0) verifyNull(Meth); JavaMethod* meth = JavaObjectVMMethod::getInternalMethod(Meth); Jnjvm* vm = JavaThread::get()->getJVM(); result = vm->internalUTF8ToStr(meth->type); END_NATIVE_EXCEPTION return result; } }