InternalNative.cpp revision b08e2b6017770e887f6072c1520b2d7f2ef6916c
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * Internal-native initialization and some common utility functions. 19 */ 20#include "Dalvik.h" 21#include "native/InternalNativePriv.h" 22 23/* 24 * Set of classes for which we provide methods. 25 * 26 * The last field, classNameHash, is filled in at startup. 27 */ 28static DalvikNativeClass gDvmNativeMethodSet[] = { 29 { "Ljava/lang/Object;", dvm_java_lang_Object, 0 }, 30 { "Ljava/lang/Class;", dvm_java_lang_Class, 0 }, 31 { "Ljava/lang/Double;", dvm_java_lang_Double, 0 }, 32 { "Ljava/lang/Float;", dvm_java_lang_Float, 0 }, 33 { "Ljava/lang/Math;", dvm_java_lang_Math, 0 }, 34 { "Ljava/lang/Runtime;", dvm_java_lang_Runtime, 0 }, 35 { "Ljava/lang/String;", dvm_java_lang_String, 0 }, 36 { "Ljava/lang/System;", dvm_java_lang_System, 0 }, 37 { "Ljava/lang/Throwable;", dvm_java_lang_Throwable, 0 }, 38 { "Ljava/lang/VMClassLoader;", dvm_java_lang_VMClassLoader, 0 }, 39 { "Ljava/lang/VMThread;", dvm_java_lang_VMThread, 0 }, 40 { "Ljava/lang/reflect/AccessibleObject;", 41 dvm_java_lang_reflect_AccessibleObject, 0 }, 42 { "Ljava/lang/reflect/Array;", dvm_java_lang_reflect_Array, 0 }, 43 { "Ljava/lang/reflect/Constructor;", 44 dvm_java_lang_reflect_Constructor, 0 }, 45 { "Ljava/lang/reflect/Field;", dvm_java_lang_reflect_Field, 0 }, 46 { "Ljava/lang/reflect/Method;", dvm_java_lang_reflect_Method, 0 }, 47 { "Ljava/lang/reflect/Proxy;", dvm_java_lang_reflect_Proxy, 0 }, 48 { "Ljava/util/concurrent/atomic/AtomicLong;", 49 dvm_java_util_concurrent_atomic_AtomicLong, 0 }, 50 { "Ldalvik/bytecode/OpcodeInfo;", dvm_dalvik_bytecode_OpcodeInfo, 0 }, 51 { "Ldalvik/system/VMDebug;", dvm_dalvik_system_VMDebug, 0 }, 52 { "Ldalvik/system/DexFile;", dvm_dalvik_system_DexFile, 0 }, 53 { "Ldalvik/system/VMRuntime;", dvm_dalvik_system_VMRuntime, 0 }, 54 { "Ldalvik/system/Zygote;", dvm_dalvik_system_Zygote, 0 }, 55 { "Ldalvik/system/VMStack;", dvm_dalvik_system_VMStack, 0 }, 56 { "Lorg/apache/harmony/dalvik/ddmc/DdmServer;", 57 dvm_org_apache_harmony_dalvik_ddmc_DdmServer, 0 }, 58 { "Lorg/apache/harmony/dalvik/ddmc/DdmVmInternal;", 59 dvm_org_apache_harmony_dalvik_ddmc_DdmVmInternal, 0 }, 60 { "Lorg/apache/harmony/dalvik/NativeTestTarget;", 61 dvm_org_apache_harmony_dalvik_NativeTestTarget, 0 }, 62 { "Lsun/misc/Unsafe;", dvm_sun_misc_Unsafe, 0 }, 63 { NULL, NULL, 0 }, 64}; 65 66 67/* 68 * Set up hash values on the class names. 69 */ 70bool dvmInternalNativeStartup() 71{ 72 DalvikNativeClass* classPtr = gDvmNativeMethodSet; 73 74 while (classPtr->classDescriptor != NULL) { 75 classPtr->classDescriptorHash = 76 dvmComputeUtf8Hash(classPtr->classDescriptor); 77 classPtr++; 78 } 79 80 gDvm.userDexFiles = dvmHashTableCreate(2, dvmFreeDexOrJar); 81 if (gDvm.userDexFiles == NULL) 82 return false; 83 84 return true; 85} 86 87/* 88 * Clean up. 89 */ 90void dvmInternalNativeShutdown() 91{ 92 dvmHashTableFree(gDvm.userDexFiles); 93} 94 95/* 96 * Search the internal native set for a match. 97 */ 98DalvikNativeFunc dvmLookupInternalNativeMethod(const Method* method) 99{ 100 const char* classDescriptor = method->clazz->descriptor; 101 const DalvikNativeClass* pClass; 102 u4 hash; 103 104 hash = dvmComputeUtf8Hash(classDescriptor); 105 pClass = gDvmNativeMethodSet; 106 while (true) { 107 if (pClass->classDescriptor == NULL) 108 break; 109 if (pClass->classDescriptorHash == hash && 110 strcmp(pClass->classDescriptor, classDescriptor) == 0) 111 { 112 const DalvikNativeMethod* pMeth = pClass->methodInfo; 113 while (true) { 114 if (pMeth->name == NULL) 115 break; 116 117 if (dvmCompareNameDescriptorAndMethod(pMeth->name, 118 pMeth->signature, method) == 0) 119 { 120 /* match */ 121 //LOGV("+++ match on %s.%s %s at %p", 122 // className, methodName, methodSignature, pMeth->fnPtr); 123 return pMeth->fnPtr; 124 } 125 126 pMeth++; 127 } 128 } 129 130 pClass++; 131 } 132 133 return NULL; 134} 135 136 137/* 138 * Magic "internal native" code stub, inserted into abstract method 139 * definitions when a class is first loaded. This throws the expected 140 * exception so we don't have to explicitly check for it in the interpreter. 141 */ 142void dvmAbstractMethodStub(const u4* args, JValue* pResult) 143{ 144 LOGD("--- called into dvmAbstractMethodStub"); 145 dvmThrowAbstractMethodError("abstract method not implemented"); 146} 147 148 149/* 150 * Verify that "obj" is non-null and is an instance of "clazz". 151 * Used to implement reflection on fields and methods. 152 * 153 * Returns "false" and throws an exception if not. 154 */ 155bool dvmVerifyObjectInClass(Object* obj, ClassObject* clazz) { 156 ClassObject* exceptionClass = NULL; 157 if (obj == NULL) { 158 exceptionClass = gDvm.exNullPointerException; 159 } else if (!dvmInstanceof(obj->clazz, clazz)) { 160 exceptionClass = gDvm.exIllegalArgumentException; 161 } 162 163 if (exceptionClass == NULL) { 164 return true; 165 } 166 167 std::string expectedClassName(dvmHumanReadableDescriptor(clazz->descriptor)); 168 std::string actualClassName; 169 if (obj != NULL) { 170 actualClassName = dvmHumanReadableDescriptor(obj->clazz->descriptor); 171 } else { 172 actualClassName = "null"; 173 } 174 dvmThrowExceptionFmt(exceptionClass, "expected receiver of type %s, but got %s", 175 expectedClassName.c_str(), actualClassName.c_str()); 176 return false; 177} 178 179/* 180 * Find a class by name, initializing it if requested. 181 */ 182ClassObject* dvmFindClassByName(StringObject* nameObj, Object* loader, 183 bool doInit) 184{ 185 ClassObject* clazz = NULL; 186 char* name = NULL; 187 char* descriptor = NULL; 188 189 if (nameObj == NULL) { 190 dvmThrowNullPointerException(NULL); 191 goto bail; 192 } 193 name = dvmCreateCstrFromString(nameObj); 194 195 /* 196 * We need to validate and convert the name (from x.y.z to x/y/z). This 197 * is especially handy for array types, since we want to avoid 198 * auto-generating bogus array classes. 199 */ 200 if (!dexIsValidClassName(name, true)) { 201 LOGW("dvmFindClassByName rejecting '%s'", name); 202 dvmThrowClassNotFoundException(name); 203 goto bail; 204 } 205 206 descriptor = dvmDotToDescriptor(name); 207 if (descriptor == NULL) { 208 goto bail; 209 } 210 211 if (doInit) 212 clazz = dvmFindClass(descriptor, loader); 213 else 214 clazz = dvmFindClassNoInit(descriptor, loader); 215 216 if (clazz == NULL) { 217 LOGVV("FAIL: load %s (%d)", descriptor, doInit); 218 Thread* self = dvmThreadSelf(); 219 Object* oldExcep = dvmGetException(self); 220 dvmAddTrackedAlloc(oldExcep, self); /* don't let this be GCed */ 221 dvmClearException(self); 222 dvmThrowChainedClassNotFoundException(name, oldExcep); 223 dvmReleaseTrackedAlloc(oldExcep, self); 224 } else { 225 LOGVV("GOOD: load %s (%d) --> %p ldr=%p", 226 descriptor, doInit, clazz, clazz->classLoader); 227 } 228 229bail: 230 free(name); 231 free(descriptor); 232 return clazz; 233} 234 235/* 236 * We insert native method stubs for abstract methods so we don't have to 237 * check the access flags at the time of the method call. This results in 238 * "native abstract" methods, which can't exist. If we see the "abstract" 239 * flag set, clear the "native" flag. 240 * 241 * We also move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED 242 * position, because the callers of this function are trying to convey 243 * the "traditional" meaning of the flags to their callers. 244 */ 245u4 dvmFixMethodFlags(u4 flags) 246{ 247 if ((flags & ACC_ABSTRACT) != 0) { 248 flags &= ~ACC_NATIVE; 249 } 250 251 flags &= ~ACC_SYNCHRONIZED; 252 253 if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) { 254 flags |= ACC_SYNCHRONIZED; 255 } 256 257 return flags & JAVA_FLAGS_MASK; 258} 259