Ejemplo n.º 1
0
// Based on dvmResolveMethod.
static void preloadDexCachesResolveMethod(DvmDex* pDvmDex,
                                          uint32_t methodIdx,
                                          MethodType methodType) {
    Method* method = dvmDexGetResolvedMethod(pDvmDex, methodIdx);
    if (method != NULL) {
        return;
    }
    const DexFile* pDexFile = pDvmDex->pDexFile;
    const DexMethodId* pMethodId = dexGetMethodId(pDexFile, methodIdx);
    ClassObject* clazz = dvmDexGetResolvedClass(pDvmDex, pMethodId->classIdx);
    if (clazz == NULL) {
        return;
    }
    // Skip static methods for uninitialized classes because a filled
    // cache entry implies the class is initialized.
    if ((methodType == METHOD_STATIC) && !dvmIsClassInitialized(clazz)) {
        return;
    }
    const char* methodName = dexStringById(pDexFile, pMethodId->nameIdx);
    DexProto proto;
    dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);

    if (methodType == METHOD_DIRECT) {
        method = dvmFindDirectMethod(clazz, methodName, &proto);
    } else if (methodType == METHOD_STATIC) {
        method = dvmFindDirectMethodHier(clazz, methodName, &proto);
    } else {
        method = dvmFindVirtualMethodHier(clazz, methodName, &proto);
    }
    if (method == NULL) {
        return;
    }
    // ALOGI("VMRuntime.preloadDexCaches found method %s.%s",
    //        clazz->descriptor, methodName);
    dvmDexSetResolvedMethod(pDvmDex, methodIdx, method);
}
Ejemplo n.º 2
0
/*
 * Find the method corresponding to "methodRef".
 *
 * We use "referrer" to find the DexFile with the constant pool that
 * "methodRef" is an index into.  We also use its class loader.  The method
 * being resolved may very well be in a different DEX file.
 *
 * If this is a static method, we ensure that the method's class is
 * initialized.
 */
Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx,
                         MethodType methodType)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    ClassObject* resClass;
    const DexMethodId* pMethodId;
    Method* resMethod;

    assert(methodType != METHOD_INTERFACE);

    LOGVV("--- resolving method %u (referrer=%s)\n", methodIdx,
          referrer->descriptor);
    pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);

    resClass = dvmResolveClass(referrer, pMethodId->classIdx, false);
    if (resClass == NULL) {
        /* can't find the class that the method is a part of */
        assert(dvmCheckException(dvmThreadSelf()));
        return NULL;
    }
    if (dvmIsInterfaceClass(resClass)) {
        /* method is part of an interface */
        dvmThrowExceptionWithClassMessage(
            "Ljava/lang/IncompatibleClassChangeError;",
            resClass->descriptor);
        return NULL;
    }

    const char* name = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
    DexProto proto;
    dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);

    /*
     * We need to chase up the class hierarchy to find methods defined
     * in super-classes.  (We only want to check the current class
     * if we're looking for a constructor; since DIRECT calls are only
     * for constructors and private methods, we don't want to walk up.)
     */
    if (methodType == METHOD_DIRECT) {
        resMethod = dvmFindDirectMethod(resClass, name, &proto);
    } else if (methodType == METHOD_STATIC) {
        resMethod = dvmFindDirectMethodHier(resClass, name, &proto);
    } else {
        resMethod = dvmFindVirtualMethodHier(resClass, name, &proto);
    }

    if (resMethod == NULL) {
        dvmThrowException("Ljava/lang/NoSuchMethodError;", name);
        return NULL;
    }

    LOGVV("--- found method %d (%s.%s)\n",
          methodIdx, resClass->descriptor, resMethod->name);

    /* see if this is a pure-abstract method */
    if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
        dvmThrowException("Ljava/lang/AbstractMethodError;", name);
        return NULL;
    }

    /*
     * If we're the first to resolve this class, we need to initialize
     * it now.  Only necessary for METHOD_STATIC.
     */
    if (methodType == METHOD_STATIC) {
        if (!dvmIsClassInitialized(resMethod->clazz) &&
                !dvmInitClass(resMethod->clazz))
        {
            assert(dvmCheckException(dvmThreadSelf()));
            return NULL;
        } else {
            assert(!dvmCheckException(dvmThreadSelf()));
        }
    } else {
        /*
         * Edge case: if the <clinit> for a class creates an instance
         * of itself, we will call <init> on a class that is still being
         * initialized by us.
         */
        assert(dvmIsClassInitialized(resMethod->clazz) ||
               dvmIsClassInitializing(resMethod->clazz));
    }

    /*
     * The class is initialized, the method has been found.  Add a pointer
     * to our data structure so we don't have to jump through the hoops again.
     */
    dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);

    return resMethod;
}