Esempio n. 1
0
File: bc.c Progetto: SinoJerk/robovm
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);
    }
}
Esempio n. 2
0
File: bc.c Progetto: SinoJerk/robovm
void _bcSetObjectArrayElement(Env* env, ObjectArray* array, jint index, Object* value) {
    if (!value) {
        array->values[index] = value;
        return;        
    }
    ENTER;
    Class* componentType = array->object.clazz->componentType;
    jboolean assignable = rvmIsAssignableFrom(env, value->clazz, componentType);
    if (!rvmExceptionCheck(env) && !assignable) {
        rvmThrowArrayStoreException(env, value->clazz, array->object.clazz);
    }
    if (!rvmExceptionCheck(env)) array->values[index] = value;
    LEAVEV;
}
Esempio n. 3
0
/**
 * Implements all abstract methods in {@code proxyClass}. This should be called after
 * {@link #addProxyMethods()} which will override all methods defined by the proxy's
 * ancestor classes (abstract or concrete).
 */
static jboolean implementAbstractInterfaceMethods(Env* env, Class* proxyClass, Interface* interface, ProxyClassData* proxyClassData) {
    if (!interface) return TRUE;

    Method* method = rvmGetMethods(env, interface->interface);
    if (rvmExceptionOccurred(env)) return FALSE;
    for (; method != NULL; method = method->next) {
        if (!METHOD_IS_CLASS_INITIALIZER(method)) {
            ProxyMethod* proxyMethod = hasMethod(env, proxyClass, method->name, method->desc);
            if (rvmExceptionOccurred(env)) return FALSE;
            if (!proxyMethod) { 
                jint access = (method->access & (~ACC_ABSTRACT)) | ACC_FINAL;
                proxyMethod = addProxyMethod(env, proxyClass, method, access, _proxy0);
                if (!proxyMethod) return FALSE;
            }
            // Record the lookup function in proxyClassData
            LookupEntry* entry = rvmAllocateMemory(env, sizeof(LookupEntry));
            if (!entry) return FALSE;
            entry->key.name = method->name;
            entry->key.desc = method->desc;
            entry->method = proxyMethod;
            HASH_ADD(hh, proxyClassData->lookupsHash, key, sizeof(LookupKey), entry);
        }
    }

    if (!implementAbstractInterfaceMethods(env, proxyClass, interface->next, proxyClassData)) return FALSE;
    Interface* interfaceInterfaces = rvmGetInterfaces(env, interface->interface);
    if (rvmExceptionCheck(env)) return FALSE;
    if (!implementAbstractInterfaceMethods(env, proxyClass, interfaceInterfaces, proxyClassData)) return FALSE;

    return TRUE;
}
Esempio n. 4
0
static jboolean getRuntimeVisibleAnnotationsIterator(Env* env, jbyte type, void* attributes, void* data) {
    ObjectArray** result = (ObjectArray**) ((void**) data)[0];
    Object* classLoader = (Object*) ((void**) data)[1];
    if (type == RUNTIME_VISIBLE_ANNOTATIONS) {
        jint length = getInt(&attributes);
        ObjectArray* annotations = rvmNewObjectArray(env, length, java_lang_annotation_Annotation, NULL, NULL);
        if (!annotations) return FALSE;
        jint i = 0;
        jint actualLength = 0;
        for (i = 0; i < length; i++) {
            jvalue value = {0};
            if (getAnnotationValue(env, &attributes, NULL, classLoader, &value, TRUE)) {
                annotations->values[actualLength++] = (Object*) value.l;
            } else if (rvmExceptionCheck(env)) {
                return FALSE;
            }
        }
        if (actualLength != length) {
            // One or more annotations could not be loaded due to a missing class.
            // Reallocate the result array and copy over the non null values.
            ObjectArray* annotations2 = rvmNewObjectArray(env, actualLength, java_lang_annotation_Annotation, NULL, NULL);
            if (!annotations2) return FALSE;
            memcpy(annotations2->values, annotations->values, actualLength * sizeof(Object*));
            annotations = annotations2;
        }
        *result = annotations;
        return FALSE; // Stop iterating
    }
    return TRUE; // Continue with next attribute
}
Esempio n. 5
0
File: bc.c Progetto: SinoJerk/robovm
void* lookupInterfaceMethod(Env* env, ClassInfoHeader* header, Object* thiz, char* name, char* desc) {
    initializeClass(env, header);
    if (rvmExceptionCheck(env)) return NULL;
    Class* ownerInterface = header->clazz;
    if (!rvmIsInstanceOf(env, thiz, ownerInterface)) {
        char message[256];
        snprintf(message, 256, "Class %s does not implement the requested interface %s", 
            rvmToBinaryClassName(env, thiz->clazz->name), rvmToBinaryClassName(env, ownerInterface->name));
        rvmThrowIncompatibleClassChangeError(env, message);
        return NULL;
    }
    Method* method = rvmGetInstanceMethod(env, thiz->clazz, name, desc);
    Object* throwable = rvmExceptionClear(env);
    if (!method && throwable->clazz != java_lang_NoSuchMethodError) { 
        rvmThrow(env, throwable);
        return NULL;
    }
    if (!method || METHOD_IS_ABSTRACT(method)) {
        rvmThrowAbstractMethodError(env, ""); // TODO: Message
        return NULL;
    }
    if (!METHOD_IS_PUBLIC(method)) {
        rvmThrowIllegalAccessError(env, ""); // TODO: Message
        return NULL;
    }
    return method->synchronizedImpl ? method->synchronizedImpl : method->impl;
}
Esempio n. 6
0
Class* rvmProxyCreateProxyClass(Env* env, Class* superclass, ClassLoader* classLoader, char* className, jint interfacesCount, Class** interfaces, 
        jint instanceDataSize, jint instanceDataOffset, unsigned short instanceRefCount, ProxyHandler handler) {

    // Allocate the proxy class.
    Class* proxyClass = rvmAllocateClass(env, className, superclass, classLoader, CLASS_TYPE_PROXY | ACC_PUBLIC | ACC_FINAL, 
        offsetof(Class, data) + sizeof(ProxyClassData), instanceDataSize, instanceDataOffset, 1, instanceRefCount, NULL, NULL);
    if (!proxyClass) return NULL;

    ProxyClassData* proxyClassData = (ProxyClassData*) proxyClass->data;
    proxyClassData->handler = handler;

    // Add interfaces
    jint i;
    for (i = 0; i < interfacesCount; i++) {
        if (!rvmAddInterface(env, proxyClass, (Class*) interfaces[i])) return NULL;
    }

    // Initialize methods to NULL to prevent rvmGetMethods() from trying to load the methods if called with this proxy class
    proxyClass->_methods = NULL;

    Class* c = proxyClass;
    while (c) {
        Interface* interface = rvmGetInterfaces(env, c);
        if (rvmExceptionCheck(env)) return NULL;
        if (!implementAbstractInterfaceMethods(env, proxyClass, interface, proxyClassData)) return NULL;
        c = c->superclass;
    }

    if (!addProxyMethods(env, proxyClass, superclass, proxyClassData)) return NULL;

    if (!rvmRegisterClass(env, proxyClass)) return NULL;

    return proxyClass;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
ObjectArray* Java_java_lang_Class_getDeclaredFields0(Env* env, Class* clazz, jboolean publicOnly) {
    if (CLASS_IS_PRIMITIVE(clazz) || CLASS_IS_ARRAY(clazz)) return NULL;

    Field* fields = rvmGetFields(env, clazz);
    if (rvmExceptionCheck(env)) return NULL;

    Field* field;
    jint length = 0;
    for (field = fields; field != NULL; field = field->next) {
        if (!publicOnly || FIELD_IS_PUBLIC(field)) {
            length++;
        }
    }

    ObjectArray* result = NULL;
    jint i = 0;
    for (field = fields; field != NULL; field = field->next) {
        if (!publicOnly || FIELD_IS_PUBLIC(field)) {
            Object* c = createFieldObject(env, field);
            if (!c) return NULL;
            if (!result) {
                result = rvmNewObjectArray(env, length, c->clazz, NULL, NULL);
                if (!result) return NULL;
            }
            result->values[i++] = c;
        }
    }

    return result;
}
Esempio n. 9
0
ObjectArray* Java_java_lang_Class_getDeclaredMethods0(Env* env, Class* clazz, jboolean publicOnly) {
    if (CLASS_IS_PRIMITIVE(clazz) || CLASS_IS_ARRAY(clazz)) return NULL;

    Method* methods = rvmGetMethods(env, clazz);
    if (rvmExceptionCheck(env)) return NULL;

    Method* method;
    jint length = 0;
    for (method = methods; method != NULL; method = method->next) {
        if (!METHOD_IS_CONSTRUCTOR(method) && !METHOD_IS_CLASS_INITIALIZER(method)) {
            if (!publicOnly || METHOD_IS_PUBLIC(method)) {
                length++;
            }
        }
    }

    ObjectArray* result = NULL;
    jint i = 0;
    for (method = methods; method != NULL; method = method->next) {
        if (!METHOD_IS_CONSTRUCTOR(method) && !METHOD_IS_CLASS_INITIALIZER(method)) {
            if (!publicOnly || METHOD_IS_PUBLIC(method)) {
                Object* c = createMethodObject(env, method);
                if (!c) return NULL;
                if (!result) {
                    result = rvmNewObjectArray(env, length, c->clazz, NULL, NULL);
                    if (!result) return NULL;
                }
                result->values[i++] = c;
            }
        }
    }

    return result;
}
Esempio n. 10
0
Method* rvmGetMethods(Env* env, Class* clazz) {
    if (clazz->_methods != &METHODS_NOT_LOADED) return clazz->_methods;

    // TODO: Double checked locking
    obtainClassLock();
    if (clazz->_methods == &METHODS_NOT_LOADED) {
        env->vm->options->loadMethods(env, clazz);
        if (clazz->_methods == &METHODS_NOT_LOADED) {
            // The class has no methods
            clazz->_methods = NULL;
        }
    }
    if (rvmExceptionCheck(env)) clazz->_methods = &METHODS_NOT_LOADED;
    releaseClassLock();
    if (rvmExceptionCheck(env)) return NULL;
    return clazz->_methods;
}
Esempio n. 11
0
Interface* rvmGetInterfaces(Env* env, Class* clazz) {
    if (clazz->_interfaces != &INTERFACES_NOT_LOADED) return clazz->_interfaces;

    // TODO: Double checked locking
    obtainClassLock();
    if (clazz->_interfaces == &INTERFACES_NOT_LOADED) {
        env->vm->options->loadInterfaces(env, clazz);
        if (clazz->_interfaces == &INTERFACES_NOT_LOADED) {
            // The class has no interfaces
            clazz->_interfaces = NULL;
        }
    }
    if (rvmExceptionCheck(env)) clazz->_interfaces = &INTERFACES_NOT_LOADED;
    releaseClassLock();
    if (rvmExceptionCheck(env)) return NULL;
    return clazz->_interfaces;
}
Esempio n. 12
0
File: bc.c Progetto: SinoJerk/robovm
Object* _bcCheckcastArray(Env* env, Class* arrayClass, Object* o) {
    if (!o) return o;
    ENTER;
    jboolean b = rvmIsAssignableFrom(env, o->clazz, arrayClass);
    if (!rvmExceptionCheck(env) && !b) {
        rvmThrowClassCastException(env, arrayClass, o->clazz);
    }
    LEAVE(o);
}
Esempio n. 13
0
Method* rvmGetMethod(Env* env, Class* clazz, const char* name, const char* desc) {
    Method* method = getMethod(env, clazz, name, desc);
    if (rvmExceptionCheck(env)) return NULL;
    if (!method) {
        rvmThrowNoSuchMethodError(env, name);
        return NULL;
    }
    return method;
}
Esempio n. 14
0
static Method* findMethod(Env* env, Class* clazz, const char* name, const char* desc) {
    Method* method = rvmGetMethods(env, clazz);
    if (rvmExceptionCheck(env)) return NULL;
    for (; method != NULL; method = method->next) {
        if (!strcmp(method->name, name) && !strcmp(method->desc, desc)) {
            return method;
        }
    }
    return NULL;
}
Esempio n. 15
0
File: bc.c Progetto: SinoJerk/robovm
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);
}
Esempio n. 16
0
Class* Java_java_lang_Class_getEnclosingClass(Env* env, Class* thiz) {
    Class* enclosingClass = rvmAttributeGetEnclosingClass(env, thiz);
    if (rvmExceptionCheck(env) && rvmExceptionOccurred(env)->clazz != java_lang_ClassNotFoundException) {
        return NULL;
    }
    if (!enclosingClass) {
        rvmExceptionClear(env);
        return rvmAttributeGetDeclaringClass(env, thiz);
    }
    return enclosingClass;
}
Esempio n. 17
0
File: bc.c Progetto: SinoJerk/robovm
Object* _bcLdcString(Env* env, Object** ptr, char* s, jint length) {
    Object* o = *ptr;
    if (o) return o;
    ENTER;
    o = rvmNewInternedStringUTF(env, s, length);
    if (!rvmExceptionCheck(env)) {
        *ptr = o;
        rvmRegisterDisappearingLink(env, (void**) ptr, o);
    }
    LEAVE(o);
}
Esempio n. 18
0
File: bc.c Progetto: SinoJerk/robovm
Object* _bcCheckcast(Env* env, ClassInfoHeader* header, Object* o) {
    if (!o) return o;
    ENTER;
    Class* clazz = ldcClass(env, header);
    if (clazz) {
        jboolean b = rvmIsAssignableFrom(env, o->clazz, clazz);
        if (!rvmExceptionCheck(env) && !b) {
            rvmThrowClassCastException(env, clazz, o->clazz);
        }
    }
    LEAVE(o);
}
Esempio n. 19
0
static void iterateAttributes(Env* env, void* attributes, jboolean (*f)(Env*, jbyte, void*, void*), void* data) {
    if (!attributes) return;

    jint i, j;
    jint length = 0;
    jint numParams = 0;
    jint count = getInt(&attributes);

    while (count > 0) {
        jbyte type = getByte(&attributes);
        if (!f(env, type, attributes, data)) {
            return;
        }
        if (rvmExceptionCheck(env)) return;

        switch (type) {
        case SOURCE_FILE:
        case SIGNATURE:
            attributes += sizeof(char*);
            break;
        case INNER_CLASS:
            attributes += 3 * sizeof(char*) + sizeof(jint);
            break;
        case ENCLOSING_METHOD:
            attributes += 3 * sizeof(char*);
            break;
        case EXCEPTIONS:
            length = getInt(&attributes);
            attributes += length * sizeof(char*);
            break;
        case ANNOTATION_DEFAULT:
            skipElementValue(&attributes);
            break;
        case RUNTIME_VISIBLE_ANNOTATIONS:
            length = getInt(&attributes);
            while (length > 0) {
                skipAnnotationElementValue(&attributes);
                length--;
            }
            break;
        case RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS:
            numParams = getInt(&attributes);
            for (i = 0; i < numParams; i++) {
                length = getInt(&attributes);
                for (j = 0; j < length; j++) {
                    skipAnnotationElementValue(&attributes);
                }
            }
            break;
        }
        count--;
    }
}
Esempio n. 20
0
static Method* getMethod(Env* env, Class* clazz, const char* name, const char* desc) {
    if (!strcmp("<init>", name) || !strcmp("<clinit>", name)) {
        // Constructors and static initializers are not inherited so we shouldn't check with the superclasses.
        return findMethod(env, clazz, name, desc);
    }

    Class* c = clazz;
    for (c = clazz; c != NULL; c = c->superclass) {
        Method* method = findMethod(env, c, name, desc);
        if (rvmExceptionCheck(env)) return NULL;
        if (method) return method;
    }

    /*
     * Check with interfaces.
     * TODO: Should we really do this? Does the JNI GetMethodID() function do this?
     */
    for (c = clazz; c != NULL; c = c->superclass) {
        Interface* interfaze = rvmGetInterfaces(env, c);
        if (rvmExceptionCheck(env)) return NULL;
        for (; interfaze != NULL; interfaze = interfaze->next) {
            Method* method = getMethod(env, interfaze->interfaze, name, desc);
            if (rvmExceptionCheck(env)) return NULL;
            if (method) return method;
        }
    }

    if (CLASS_IS_INTERFACE(clazz)) {
        /*
         * Class is an interface so check with java.lang.Object.
         * TODO: Should we really do this? Does the JNI GetMethodID() function do this?
         */
        return getMethod(env, java_lang_Object, name, desc);
    }

    return NULL;
}
Esempio n. 21
0
Method* rvmFindMethodAtAddress(Env* env, void* address) {
    Class* clazz = env->vm->options->findClassAt(env, address);
    if (!clazz) return NULL;
    Method* method = rvmGetMethods(env, clazz);
    if (rvmExceptionCheck(env)) return NULL;
    for (; method != NULL; method = method->next) {
        void* start = method->impl;
        void* end = start + method->size;
        if (start && address >= start && address < end) {
            return method;
        }
    }
    // TODO: We should never end up here
    return NULL;
}
Esempio n. 22
0
ObjectArray* Java_java_lang_Class_getInterfaces(Env* env, Class* thiz) {
    Interface* interfaces = rvmGetInterfaces(env, thiz);
    if (rvmExceptionCheck(env)) return NULL;
    Interface* interfaze;
    jint length = 0;
    LL_FOREACH(interfaces, interfaze) {
        length++;
    }
    ObjectArray* result = rvmNewObjectArray(env, length, java_lang_Class, NULL, NULL);
    if (!result) return NULL;
    jint i = 0;
    LL_FOREACH(interfaces, interfaze) {
        result->values[i++] = (Object*) interfaze->interfaze;
    }
    return result;
}
Esempio n. 23
0
jboolean rvmIsAssignableFrom(Env* env, Class* s, Class* t) {
    // TODO: What if s or t are NULL?
    if (s == t || t == java_lang_Object) {
        return TRUE;
    }

    if (CLASS_IS_ARRAY(s)) {
        if (t == java_io_Serializable) {
            return TRUE;
        }
        if (t == java_lang_Cloneable) {
            return TRUE;
        }
        if (!CLASS_IS_ARRAY(t)) {
            return FALSE;
        }
        Class* componentType = s->componentType;
        if (CLASS_IS_PRIMITIVE(componentType)) {
            // s is a primitive array and can only be assigned to 
            // class t if s == t or t == (Object|Serializable|Cloneable). But we 
            // already know that s != t and t != (Object|Serializable|Cloneable)
            return FALSE;
        }
        return rvmIsAssignableFrom(env, componentType, t->componentType);
    }

    if (CLASS_IS_INTERFACE(t)) {
        // s or any of its parents must implement the interface t
        for (; s; s = s->superclass) {
            Interface* interface = rvmGetInterfaces(env, s);
            if (rvmExceptionCheck(env)) return FALSE;
            for (; interface != NULL; interface = interface->next) {
                if (rvmIsAssignableFrom(env, interface->interface, t)) {
                    return TRUE;
                }
            }
        }
        return FALSE;
    }

    while (s && s != t) {
        s = s->superclass;
    }
    return s ? TRUE : FALSE;
}
Esempio n. 24
0
File: bc.c Progetto: justinsb/robovm
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;
    }
}
Esempio n. 25
0
static void signalHandler_npe_so(int signum, siginfo_t* info, void* context) {
    // SIGSEGV/SIGBUS are synchronous signals so we shouldn't have to worry about only calling
    // async-signal-safe functions here.
    Env* env = rvmGetEnv();
    if (env && rvmIsNonNativeFrame(env)) {
        // We now know the fault occurred in non-native code.
        void* faultAddr = info->si_addr;
        void* stackAddr = env->currentThread->stackAddr;
        Class* exClass = NULL;
        if (faultAddr < stackAddr && faultAddr >= (void*) (stackAddr - THREAD_STACK_GUARD_SIZE)) {
            // StackOverflowError
            exClass = java_lang_StackOverflowError;
        } else {
            // At least on Linux x86 it seems like si_addr isn't always 0x0 even
            // if a read of address 0x0 triggered SIGSEGV so we assume 
            // everything that isn't a stack overflow is a read of address 0x0
            // and throw NullPointerException.
            exClass = java_lang_NullPointerException;
        }

        if (exClass) {
            Frame fakeFrame;
            fakeFrame.prev = (Frame*) getFramePointer((ucontext_t*) context);
            fakeFrame.returnAddress = getPC((ucontext_t*) context);
            Object* throwable = NULL;
            CallStack* callStack = captureCallStackFromFrame(env, &fakeFrame);
            if (callStack) {
                throwable = rvmAllocateObject(env, exClass);
                if (throwable) {
                    rvmCallVoidClassMethod(env, exClass, throwableInitMethod, throwable, PTR_TO_LONG(callStack));
                    if (rvmExceptionCheck(env)) {
                        throwable = NULL;
                    }
                }
            }
            if (!throwable) {
                throwable = rvmExceptionClear(env);
            }
            rvmRaiseException(env, throwable); // Never returns!
        }
    }
}
Esempio n. 26
0
Env* rvmStartup(Options* options) {
    // TODO: Error handling

    TRACE("Initializing logging");
    if (!rvmInitLog(options)) return NULL;

#if defined(IOS) && (defined(RVM_ARMV7) || defined(RVM_THUMBV7))
    // Enable IEEE-754 denormal support.
    // Without this the VFP treats numbers that are close to zero as zero itself.
    // See http://developer.apple.com/library/ios/#technotes/tn2293/_index.html.
    fenv_t fenv;
    fegetenv(&fenv);
    fenv.__fpscr &= ~__fpscr_flush_to_zero;
    fesetenv(&fenv);
#endif
    // print PID if it was requested
    if(options->printPID) {
        pid_t pid = getpid();
        if(options->pidFile) {
            FILE* f = fopen(options->pidFile, "w");
            if (!f) return NULL;
            fprintf(f, "%d", pid);
            fclose(f);
        } else {
            fprintf(stderr, "[DEBUG] %s: pid=%d\n", LOG_TAG, pid);
        }
    }

    // setup the TCP channel socket and wait
    // for the debugger to connect
    if(options->enableHooks) {
        if(!rvmHookSetupTCPChannel(options)) return NULL;
        if(!rvmHookHandshake(options)) return NULL;
    }

    TRACE("Initializing GC");
    if (!initGC(options)) return NULL;

    // Ignore SIGPIPE signals. SIGPIPE interrupts write() calls which we don't
    // want. Dalvik does this too in dalvikvm/Main.cpp.
    if (!ignoreSignal(SIGPIPE)) return NULL;

    // Ignore SIGXFSZ signals. SIGXFSZ is raised when writing beyond the RLIMIT_FSIZE
    // of the current process (at least on Darwin) using pwrite().
    if (!ignoreSignal(SIGXFSZ)) return NULL;

    VM* vm = rvmCreateVM(options);
    if (!vm) return NULL;

    Env* env = rvmCreateEnv(vm);
    if (!env) return NULL;
    // TODO: What if we can't allocate Env?

    if (!initClasspathEntries(env, options->resourcesPath, options->rawBootclasspath, &options->bootclasspath)) return NULL;
    if (!initClasspathEntries(env, options->resourcesPath, options->rawClasspath, &options->classpath)) return NULL;

    // Call init on modules
    TRACE("Initializing classes");
    if (!rvmInitClasses(env)) return NULL;
    TRACE("Initializing memory");
    if (!rvmInitMemory(env)) return NULL;
    TRACE("Initializing methods");
    if (!rvmInitMethods(env)) return NULL;
    TRACE("Initializing strings");
    if (!rvmInitStrings(env)) return NULL;
    TRACE("Initializing monitors");
    if (!rvmInitMonitors(env)) return NULL;
    TRACE("Initializing proxy");
    if (!rvmInitProxy(env)) return NULL;
    TRACE("Initializing threads");
    if (!rvmInitThreads(env)) return NULL;
    TRACE("Initializing attributes");
    if (!rvmInitAttributes(env)) return NULL;
    TRACE("Initializing primitive wrapper classes");
    if (!rvmInitPrimitiveWrapperClasses(env)) return NULL;
    TRACE("Initializing exceptions");
    if (!rvmInitExceptions(env)) return NULL;
    TRACE("Initializing signals");
    if (!rvmInitSignals(env)) return NULL;
    TRACE("Initializing JNI");
    if (!rvmInitJNI(env)) return NULL;

    // Initialize the RoboVM rt JNI code
//    RT_JNI_OnLoad(&vm->javaVM, NULL);
    // Initialize the dalvik rt JNI code
    TRACE("Initializing dalvik's runtime JNI code");
    registerCoreLibrariesJni((JNIEnv*) env);

#ifdef DARWIN
    TRACE("Initializing JAR NSURLProtocol");
    registerJARURLProtocol();
#endif

    TRACE("Creating system ClassLoader");
    systemClassLoader = rvmGetSystemClassLoader(env);
    if (rvmExceptionOccurred(env)) goto error_system_ClassLoader;
    env->currentThread->threadObj->contextClassLoader = systemClassLoader;

    TRACE("Initialization done");
    env->vm->initialized = TRUE;
    
    // Start Daemons
    TRACE("Starting Daemons");
    java_lang_Daemons = rvmFindClassUsingLoader(env, "java/lang/Daemons", NULL);
    if (!java_lang_Daemons) goto error_daemons;
    java_lang_Daemons_start = rvmGetClassMethod(env, java_lang_Daemons, "start", "()V");
    if (!java_lang_Daemons_start) goto error_daemons;
    rvmCallVoidClassMethod(env, java_lang_Daemons, java_lang_Daemons_start);
    if (rvmExceptionCheck(env)) goto error_daemons;
    TRACE("Daemons started");

    jboolean errorDuringSetup = FALSE;

    //If our options has any properties, let's set them before we call our main.
    if (options->properties) {
        //First, find java.lang.System, which has the setProperty method.
        Class* clazz = rvmFindClassUsingLoader(env, "java/lang/System", NULL);
        if (clazz) {
            //Get the setProperty method.
            Method* method = rvmGetClassMethod(env, clazz, "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
            if (method) {
                SystemProperty* property = options->properties;

                //Go through all of our properties and add each one in turn by calling setProperty.
                while (property != NULL) {
                    Object* key = NULL;
                    Object* value = NULL;
                    //The key is not allowed to be an empty string, so don't set it if we don't get a key.
                    if(property->key && strlen(property->key) > 0) {
                        key = rvmNewStringUTF(env, property->key, -1);
                    } else {
                        FATAL("Cannot have empty key in system property.");
                        errorDuringSetup = TRUE;
                        break;
                    }
                    if (property->value) {
                        value = rvmNewStringUTF(env, property->value, -1);
                    } else {
                        value = rvmNewStringUTF(env, "", -1);
                    }

                    if (key && value) {
                        rvmCallObjectClassMethod(env, clazz, method, key, value);
                    } else {
                        if (!key) {
                            FATALF("Error creating string from system property key: %s", property->key);
                        }
                        if (!value) {
                            FATALF("Error creating string from system property value: %s", property->value);
                        }
                        errorDuringSetup = TRUE;
                        break;
                    }
                    property = property->next; //Advance to the next property.
                }
            }
        }
    }

    return (errorDuringSetup) ? NULL : env;

error_daemons:
error_system_ClassLoader:
    rvmDetachCurrentThread(env->vm, TRUE, FALSE);

    return NULL;
}
Esempio n. 27
0
jboolean rvmHasMethod(Env* env, Class* clazz, const char* name, const char* desc) {
    Method* method = getMethod(env, clazz, name, desc);
    if (rvmExceptionCheck(env)) return FALSE;
    return method ? TRUE : FALSE;
}
Esempio n. 28
0
static jboolean ExceptionCheck(JNIEnv* env) {
    return rvmExceptionCheck((Env*) env);
}
Esempio n. 29
0
Env* rvmStartup(Options* options) {
    // TODO: Error handling

    TRACE("Initializing GC");
    if (!initGC(options)) return NULL;

    VM* vm = rvmCreateVM(options);
    if (!vm) return NULL;

    Env* env = rvmCreateEnv(vm);
    if (!env) return NULL;
    // TODO: What if we can't allocate Env?

    if (!initClasspathEntries(env, options->basePath, options->rawBootclasspath, &options->bootclasspath)) return NULL;
    if (!initClasspathEntries(env, options->basePath, options->rawClasspath, &options->classpath)) return NULL;

    // Call init on modules
    TRACE("Initializing logging");
    if (!rvmInitLog(env)) return NULL;
    TRACE("Initializing classes");
    if (!rvmInitClasses(env)) return NULL;
    TRACE("Initializing methods");
    if (!rvmInitMethods(env)) return NULL;
    TRACE("Initializing strings");
    if (!rvmInitStrings(env)) return NULL;
    TRACE("Initializing monitors");
    if (!rvmInitMonitors(env)) return NULL;
    TRACE("Initializing threads");
    if (!rvmInitThreads(env)) return NULL;
    TRACE("Initializing attributes");
    if (!rvmInitAttributes(env)) return NULL;
    TRACE("Initializing primitive wrapper classes");
    if (!rvmInitPrimitiveWrapperClasses(env)) return NULL;
    TRACE("Initializing exceptions");
    if (!rvmInitExceptions(env)) return NULL;
    TRACE("Initializing signals");
    if (!rvmInitSignals(env)) return NULL;
    TRACE("Initializing memory");
    if (!rvmInitMemory(env)) return NULL;

    // Initialize the RoboVM rt JNI code
//    RT_JNI_OnLoad(&vm->javaVM, NULL);
    // Initialize dalvik's JNIHelp code in libnativehelper
    TRACE("Initializing dalvik's libnativehelper");
    registerJniHelp((JNIEnv*) env);
    // Initialize the dalvik rt JNI code
    TRACE("Initializing dalvik's runtime JNI code");
    registerCoreLibrariesJni((JNIEnv*) env);

    TRACE("Creating system ClassLoader");
    systemClassLoader = rvmGetSystemClassLoader(env);
    if (rvmExceptionOccurred(env)) goto error_system_ClassLoader;
    env->currentThread->threadObj->contextClassLoader = systemClassLoader;

    TRACE("Initialization done");

    // Start Daemons
    TRACE("Starting Daemons");
    java_lang_Daemons = rvmFindClassUsingLoader(env, "java/lang/Daemons", NULL);
    if (!java_lang_Daemons) goto error_daemons;
    java_lang_Daemons_start = rvmGetClassMethod(env, java_lang_Daemons, "start", "()V");
    if (!java_lang_Daemons_start) goto error_daemons;
    rvmCallVoidClassMethod(env, java_lang_Daemons, java_lang_Daemons_start);
    if (rvmExceptionCheck(env)) goto error_daemons;
    TRACE("Daemons started");

    return env;

error_daemons:
error_system_ClassLoader:
    rvmDetachCurrentThread(env->vm, TRUE);

    return NULL;
}
Esempio n. 30
0
static jboolean getAnnotationValue(Env* env, void** attributes, Class* expectedAnnotationClass, Object* classLoader,
        jvalue* result, jboolean ignoreClassNotFound) {

    char* annotationTypeName = getString(attributes);
    if (expectedAnnotationClass && strncmp(&annotationTypeName[1], expectedAnnotationClass->name, strlen(expectedAnnotationClass->name))) {
        return throwFormatError(env, rvmFromBinaryClassName(env, expectedAnnotationClass->name));
    }

    Class* annotationClass = expectedAnnotationClass;
    if (!annotationClass) {
        annotationClass = rvmFindClassByDescriptor(env, annotationTypeName, classLoader);
        if (!annotationClass) {
            if (ignoreClassNotFound && rvmExceptionOccurred(env)->clazz == java_lang_ClassNotFoundException) {
                rvmExceptionClear(env);
                jint length = getInt(attributes);
                for (jint i = 0; i < length; i++) {
                    getString(attributes);
                    skipElementValue(attributes);
                }
            }
            return FALSE;
        }
    }

    // Find the annotation impl class
    Class* annotationImplClass = findAnnotationImplClass(env, annotationClass, classLoader);
    if (rvmExceptionCheck(env)) return FALSE;

    jint length = getInt(attributes);
    if (length == 0) {
        // No member values specified. Use a singleton instance.
        Method* factoryMethod = rvmGetClassMethod(env, annotationImplClass, "$createSingleton", "()Ljava/lang/Object;");
        if (rvmExceptionCheck(env)) return FALSE;
        Object* annotationObject = rvmCallObjectClassMethod(env, annotationImplClass, factoryMethod);
        if (rvmExceptionCheck(env)) return FALSE;
        result->l = (jobject) annotationObject;
        return TRUE;
    }

    // Call the annotation impl $create() method
    Method* factoryMethod = rvmGetClassMethod(env, annotationImplClass, "$create", "()Ljava/lang/Object;");
    if (rvmExceptionCheck(env)) return FALSE;
    Object* annotationObject = rvmCallObjectClassMethod(env, annotationImplClass, factoryMethod);
    if (rvmExceptionCheck(env)) return FALSE;

    jint i = 0;
    for (i = 0; i < length; i++) {
        char* name = getString(attributes);
        Method* method = getAnnotationValueMethod(env, annotationClass, name);
        if (rvmExceptionCheck(env)) return FALSE;
        if (!method) {
            skipElementValue(attributes);
        } else {
            const char* memberDesc = rvmGetReturnType(method->desc);
            Class* type = findType(env, memberDesc, method->clazz->classLoader);
            Object* value = NULL;
            if (!type) {
                value = rvmExceptionClear(env);
            } else {
                jvalue v = {0};
                if (!parseElementValue(env, attributes, type, classLoader, &v)) {
                    value = rvmExceptionClear(env);
                } else {
                    value = rvmBox(env, type, &v);
                }
            }

            InstanceField* field = getAnnotationMemberField(env, annotationImplClass, method->name);
            if (!field) return FALSE;

            rvmSetObjectInstanceFieldValue(env, annotationObject, field, value);
            if (rvmExceptionCheck(env)) return FALSE;
        }
    }

    result->l = (jobject) annotationObject;
    return TRUE;
}