am afe3a013: (-s ours) am 288f2280: Revert "Fix alignment when recompacting a DexMerger result. do not merge."
* commit 'afe3a0131e75367759e1d7a69cec0aac2a45524c':
Revert "Fix alignment when recompacting a DexMerger result. do not merge."
diff --git a/vm/Globals.h b/vm/Globals.h
index 3bef865..565c92a 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -90,6 +90,9 @@
size_t heapStartingSize;
size_t heapMaximumSize;
size_t heapGrowthLimit;
+ double heapTargetUtilization;
+ size_t heapMinFree;
+ size_t heapMaxFree;
size_t stackSize;
size_t mainThreadStackSize;
diff --git a/vm/Init.cpp b/vm/Init.cpp
index 5e3711e..11d884e 100644
--- a/vm/Init.cpp
+++ b/vm/Init.cpp
@@ -23,7 +23,10 @@
#include <signal.h>
#include <limits.h>
#include <ctype.h>
+#include <sys/mount.h>
#include <sys/wait.h>
+#include <linux/fs.h>
+#include <cutils/fs.h>
#include <unistd.h>
#include "Dalvik.h"
@@ -918,6 +921,36 @@
dvmFprintf(stderr, "Invalid -XX:HeapGrowthLimit option '%s'\n", argv[i]);
return -1;
}
+ } else if (strncmp(argv[i], "-XX:HeapMinFree=", 16) == 0) {
+ size_t val = parseMemOption(argv[i] + 16, 1024);
+ if (val != 0) {
+ gDvm.heapMinFree = val;
+ } else {
+ dvmFprintf(stderr, "Invalid -XX:HeapMinFree option '%s'\n", argv[i]);
+ return -1;
+ }
+ } else if (strncmp(argv[i], "-XX:HeapMaxFree=", 16) == 0) {
+ size_t val = parseMemOption(argv[i] + 16, 1024);
+ if (val != 0) {
+ gDvm.heapMaxFree = val;
+ } else {
+ dvmFprintf(stderr, "Invalid -XX:HeapMaxFree option '%s'\n", argv[i]);
+ return -1;
+ }
+ } else if (strncmp(argv[i], "-XX:HeapTargetUtilization=", 26) == 0) {
+ const char* start = argv[i] + 26;
+ const char* end = start;
+ double val = strtod(start, const_cast<char**>(&end));
+ // Ensure that we have a value, there was no cruft after it and it
+ // satisfies a sensible range.
+ bool sane_val = (start != end) && (end[0] == '\0') &&
+ (val >= 0.1) && (val <= 0.9);
+ if (sane_val) {
+ gDvm.heapTargetUtilization = val;
+ } else {
+ dvmFprintf(stderr, "Invalid -XX:HeapTargetUtilization option '%s'\n", argv[i]);
+ return -1;
+ }
} else if (strncmp(argv[i], "-Xss", 4) == 0) {
size_t val = parseMemOption(argv[i]+4, 1);
if (val != 0) {
@@ -1206,6 +1239,15 @@
gDvm.heapGrowthLimit = 0; // 0 means no growth limit
gDvm.stackSize = kDefaultStackSize;
gDvm.mainThreadStackSize = kDefaultStackSize;
+ // When the heap is less than the maximum or growth limited size,
+ // fix the free portion of the heap. The utilization is the ratio
+ // of live to free memory, 0.5 implies half the heap is available
+ // to allocate into before a GC occurs. Min free and max free
+ // force the free memory to never be smaller than min free or
+ // larger than max free.
+ gDvm.heapTargetUtilization = 0.5;
+ gDvm.heapMaxFree = 2 * 1024 * 1024;
+ gDvm.heapMinFree = gDvm.heapMaxFree / 4;
gDvm.concurrentMarkSweep = true;
@@ -1238,7 +1280,6 @@
gDvm.constInit = false;
gDvm.commonInit = false;
- gDvmJit.disableOpt = 1<<kMethodInlining;
#else
gDvm.executionMode = kExecutionModeInterpFast;
#endif
@@ -1597,6 +1638,32 @@
/* zygote goes into its own process group */
setpgid(0,0);
+ // See storage config details at http://source.android.com/tech/storage/
+ // Create private mount namespace shared by all children
+ if (unshare(CLONE_NEWNS) == -1) {
+ SLOGE("Failed to unshare(): %s", strerror(errno));
+ return -1;
+ }
+
+ // Mark rootfs as being a slave so that changes from default
+ // namespace only flow into our children.
+ if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) {
+ SLOGE("Failed to mount() rootfs as MS_SLAVE: %s", strerror(errno));
+ return -1;
+ }
+
+ // Create a staging tmpfs that is shared by our children; they will
+ // bind mount storage into their respective private namespaces, which
+ // are isolated from each other.
+ const char* target_base = getenv("EMULATED_STORAGE_TARGET");
+ if (target_base != NULL) {
+ if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV,
+ "uid=0,gid=1028,mode=0050") == -1) {
+ SLOGE("Failed to mount tmpfs to %s: %s", target_base, strerror(errno));
+ return -1;
+ }
+ }
+
return true;
}
diff --git a/vm/Native.cpp b/vm/Native.cpp
index be719a7..8892c2a 100644
--- a/vm/Native.cpp
+++ b/vm/Native.cpp
@@ -385,6 +385,7 @@
if (handle == NULL) {
*detail = strdup(dlerror());
+ ALOGE("dlopen(\"%s\") failed: %s", pathName, *detail);
return false;
}
diff --git a/vm/alloc/HeapSource.cpp b/vm/alloc/HeapSource.cpp
index cd2f4df..ee40af82 100644
--- a/vm/alloc/HeapSource.cpp
+++ b/vm/alloc/HeapSource.cpp
@@ -34,9 +34,6 @@
static void trimHeaps();
#define HEAP_UTILIZATION_MAX 1024
-#define DEFAULT_HEAP_UTILIZATION 512 // Range 1..HEAP_UTILIZATION_MAX
-#define HEAP_IDEAL_FREE (2 * 1024 * 1024)
-#define HEAP_MIN_FREE (HEAP_IDEAL_FREE / 4)
/* How long to wait after a GC before performing a heap trim
* operation to reclaim unused pages.
@@ -134,6 +131,18 @@
*/
size_t softLimit;
+ /* Minimum number of free bytes. Used with the target utilization when
+ * setting the softLimit. Never allows less bytes than this to be free
+ * when the heap size is below the maximum size or growth limit.
+ */
+ size_t minFree;
+
+ /* Maximum number of free bytes. Used with the target utilization when
+ * setting the softLimit. Never allows more bytes than this to be free
+ * when the heap size is below the maximum size or growth limit.
+ */
+ size_t maxFree;
+
/* The heaps; heaps[0] is always the active heap,
* which new objects should be allocated from.
*/
@@ -393,7 +402,7 @@
size_t overhead = base - hs->heaps[0].base;
assert(((size_t)hs->heaps[0].base & (SYSTEM_PAGE_SIZE - 1)) == 0);
- if (overhead + HEAP_MIN_FREE >= hs->maximumSize) {
+ if (overhead + hs->minFree >= hs->maximumSize) {
LOGE_HEAP("No room to create any more heaps "
"(%zd overhead, %zd max)",
overhead, hs->maximumSize);
@@ -401,11 +410,11 @@
}
size_t morecoreStart = SYSTEM_PAGE_SIZE;
heap.maximumSize = hs->growthLimit - overhead;
- heap.concurrentStartBytes = HEAP_MIN_FREE - CONCURRENT_START;
+ heap.concurrentStartBytes = hs->minFree - CONCURRENT_START;
heap.base = base;
heap.limit = heap.base + heap.maximumSize;
heap.brk = heap.base + morecoreStart;
- heap.msp = createMspace(base, morecoreStart, HEAP_MIN_FREE);
+ heap.msp = createMspace(base, morecoreStart, hs->minFree);
if (heap.msp == NULL) {
return false;
}
@@ -577,7 +586,9 @@
goto fail;
}
- hs->targetUtilization = DEFAULT_HEAP_UTILIZATION;
+ hs->targetUtilization = gDvm.heapTargetUtilization * HEAP_UTILIZATION_MAX;
+ hs->minFree = gDvm.heapMinFree;
+ hs->maxFree = gDvm.heapMaxFree;
hs->startSize = startSize;
hs->maximumSize = maximumSize;
hs->growthLimit = growthLimit;
@@ -588,6 +599,16 @@
hs->hasGcThread = false;
hs->heapBase = (char *)base;
hs->heapLength = length;
+
+ if (hs->maxFree > hs->maximumSize) {
+ hs->maxFree = hs->maximumSize;
+ }
+ if (hs->minFree < CONCURRENT_START) {
+ hs->minFree = CONCURRENT_START;
+ } else if (hs->minFree > hs->maxFree) {
+ hs->minFree = hs->maxFree;
+ }
+
if (!addInitialHeap(hs, msp, growthLimit)) {
LOGE_HEAP("Can't add initial heap");
goto fail;
@@ -1242,23 +1263,21 @@
/*
* Given the size of a live set, returns the ideal heap size given
* the current target utilization and MIN/MAX values.
- *
- * targetUtilization is in the range 1..HEAP_UTILIZATION_MAX.
*/
-static size_t getUtilizationTarget(size_t liveSize, size_t targetUtilization)
+static size_t getUtilizationTarget(const HeapSource* hs, size_t liveSize)
{
/* Use the current target utilization ratio to determine the
* ideal heap size based on the size of the live set.
*/
- size_t targetSize = (liveSize / targetUtilization) * HEAP_UTILIZATION_MAX;
+ size_t targetSize = (liveSize / hs->targetUtilization) * HEAP_UTILIZATION_MAX;
/* Cap the amount of free space, though, so we don't end up
* with, e.g., 8MB of free space when the live set size hits 8MB.
*/
- if (targetSize > liveSize + HEAP_IDEAL_FREE) {
- targetSize = liveSize + HEAP_IDEAL_FREE;
- } else if (targetSize < liveSize + HEAP_MIN_FREE) {
- targetSize = liveSize + HEAP_MIN_FREE;
+ if (targetSize > liveSize + hs->maxFree) {
+ targetSize = liveSize + hs->maxFree;
+ } else if (targetSize < liveSize + hs->minFree) {
+ targetSize = liveSize + hs->minFree;
}
return targetSize;
}
@@ -1285,8 +1304,7 @@
* the current heap.
*/
size_t currentHeapUsed = heap->bytesAllocated;
- size_t targetHeapSize =
- getUtilizationTarget(currentHeapUsed, hs->targetUtilization);
+ size_t targetHeapSize = getUtilizationTarget(hs, currentHeapUsed);
/* The ideal size includes the old heaps; add overhead so that
* it can be immediately subtracted again in setIdealFootprint().
diff --git a/vm/alloc/MarkSweep.cpp b/vm/alloc/MarkSweep.cpp
index 268d880..eb739e5 100644
--- a/vm/alloc/MarkSweep.cpp
+++ b/vm/alloc/MarkSweep.cpp
@@ -556,9 +556,7 @@
{
GcHeap *h = gDvm.gcHeap;
const u1 *base, *limit, *ptr, *dirty;
- size_t footprint;
- footprint = dvmHeapSourceGetValue(HS_FOOTPRINT, NULL, 0);
base = &h->cardTableBase[0];
limit = dvmCardFromAddr((u1 *)dvmHeapSourceGetLimit());
assert(limit <= &h->cardTableBase[h->cardTableLength]);
diff --git a/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.cpp b/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.cpp
index 222b880..84744b5 100644
--- a/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.cpp
+++ b/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#if 0
+
/*
* Rebuild the interpreter frame then punt to the interpreter to execute
* instruction at specified PC.
@@ -445,3 +447,11 @@
selfVerificationBranchInsertPass(cUnit);
#endif
}
+
+#else
+
+void dvmCompilerMethodMIR2LIR(CompilationUnit *cUnit) {
+ // Method-based JIT not supported for ARM.
+}
+
+#endif
diff --git a/vm/compiler/codegen/x86/CodegenInterface.cpp b/vm/compiler/codegen/x86/CodegenInterface.cpp
index aade180..c99fadd 100644
--- a/vm/compiler/codegen/x86/CodegenInterface.cpp
+++ b/vm/compiler/codegen/x86/CodegenInterface.cpp
@@ -189,8 +189,7 @@
void dvmCompilerMethodMIR2LIR(CompilationUnit *cUnit)
{
- ALOGE("Method-based JIT not supported for the x86 target");
- dvmAbort();
+ // Method-based JIT not supported for x86.
}
void dvmJitScanAllClassPointers(void (*callback)(void *))
diff --git a/vm/native/dalvik_system_Zygote.cpp b/vm/native/dalvik_system_Zygote.cpp
index 28d8d2d..269b961 100644
--- a/vm/native/dalvik_system_Zygote.cpp
+++ b/vm/native/dalvik_system_Zygote.cpp
@@ -31,7 +31,13 @@
#include <errno.h>
#include <paths.h>
#include <sys/personality.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <linux/fs.h>
+#include <cutils/fs.h>
#include <cutils/sched_policy.h>
+#include <cutils/multiuser.h>
+#include <sched.h>
#if defined(HAVE_PRCTL)
# include <sys/prctl.h>
@@ -48,6 +54,14 @@
DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
};
+/* must match values in dalvik.system.Zygote */
+enum {
+ MOUNT_EXTERNAL_NONE = 0,
+ MOUNT_EXTERNAL_SINGLEUSER = 1,
+ MOUNT_EXTERNAL_MULTIUSER = 2,
+ MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
+};
+
/*
* This signal handler is for zygote mode, since the zygote
* must reap its children
@@ -229,6 +243,98 @@
return 0;
}
+/*
+ * Create a private mount namespace and bind mount appropriate emulated
+ * storage for the given user.
+ */
+static int mountEmulatedStorage(uid_t uid, u4 mountMode) {
+ // See storage config details at http://source.android.com/tech/storage/
+ userid_t userid = multiuser_get_user_id(uid);
+
+ // Create a second private mount namespace for our process
+ if (unshare(CLONE_NEWNS) == -1) {
+ SLOGE("Failed to unshare(): %s", strerror(errno));
+ return -1;
+ }
+
+ // Create bind mounts to expose external storage
+ if (mountMode == MOUNT_EXTERNAL_MULTIUSER
+ || mountMode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+ // These paths must already be created by init.rc
+ const char* source = getenv("EMULATED_STORAGE_SOURCE");
+ const char* target = getenv("EMULATED_STORAGE_TARGET");
+ const char* legacy = getenv("EXTERNAL_STORAGE");
+ if (source == NULL || target == NULL || legacy == NULL) {
+ SLOGE("Storage environment undefined; unable to provide external storage");
+ return -1;
+ }
+
+ // Prepare source paths
+ char source_user[PATH_MAX];
+ char source_obb[PATH_MAX];
+ char target_user[PATH_MAX];
+
+ // /mnt/shell/emulated/0
+ snprintf(source_user, PATH_MAX, "%s/%d", source, userid);
+ // /mnt/shell/emulated/obb
+ snprintf(source_obb, PATH_MAX, "%s/obb", source);
+ // /storage/emulated/0
+ snprintf(target_user, PATH_MAX, "%s/%d", target, userid);
+
+ if (fs_prepare_dir(source_user, 0000, 0, 0) == -1
+ || fs_prepare_dir(source_obb, 0000, 0, 0) == -1
+ || fs_prepare_dir(target_user, 0000, 0, 0) == -1) {
+ return -1;
+ }
+
+ if (mountMode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+ // Mount entire external storage tree for all users
+ if (mount(source, target, NULL, MS_BIND, NULL) == -1) {
+ SLOGE("Failed to mount %s to %s: %s", source, target, strerror(errno));
+ return -1;
+ }
+ } else {
+ // Only mount user-specific external storage
+ if (mount(source_user, target_user, NULL, MS_BIND, NULL) == -1) {
+ SLOGE("Failed to mount %s to %s: %s", source_user, target_user, strerror(errno));
+ return -1;
+ }
+ }
+
+ // Now that user is mounted, prepare and mount OBB storage
+ // into place for current user
+ char target_android[PATH_MAX];
+ char target_obb[PATH_MAX];
+
+ // /storage/emulated/0/Android
+ snprintf(target_android, PATH_MAX, "%s/%d/Android", target, userid);
+ // /storage/emulated/0/Android/obb
+ snprintf(target_obb, PATH_MAX, "%s/%d/Android/obb", target, userid);
+
+ if (fs_prepare_dir(target_android, 0000, 0, 0) == -1
+ || fs_prepare_dir(target_obb, 0000, 0, 0) == -1
+ || fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
+ return -1;
+ }
+ if (mount(source_obb, target_obb, NULL, MS_BIND, NULL) == -1) {
+ SLOGE("Failed to mount %s to %s: %s", source_obb, target_obb, strerror(errno));
+ return -1;
+ }
+
+ // Finally, mount user-specific path into place for legacy users
+ if (mount(target_user, legacy, NULL, MS_BIND | MS_REC, NULL) == -1) {
+ SLOGE("Failed to mount %s to %s: %s", target_user, legacy, strerror(errno));
+ return -1;
+ }
+
+ } else {
+ SLOGE("Mount mode %d unsupported", mountMode);
+ return -1;
+ }
+
+ return 0;
+}
+
/* native public static int fork(); */
static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult)
{
@@ -390,6 +496,7 @@
ArrayObject* gids = (ArrayObject *)args[2];
u4 debugFlags = args[3];
ArrayObject *rlimits = (ArrayObject *)args[4];
+ u4 mountMode = MOUNT_EXTERNAL_NONE;
int64_t permittedCapabilities, effectiveCapabilities;
#ifdef HAVE_SELINUX
char *seInfo = NULL;
@@ -407,9 +514,10 @@
permittedCapabilities = args[5] | (int64_t) args[6] << 32;
effectiveCapabilities = args[7] | (int64_t) args[8] << 32;
} else {
+ mountMode = args[5];
permittedCapabilities = effectiveCapabilities = 0;
#ifdef HAVE_SELINUX
- StringObject* seInfoObj = (StringObject*)args[5];
+ StringObject* seInfoObj = (StringObject*)args[6];
if (seInfoObj) {
seInfo = dvmCreateCstrFromString(seInfoObj);
if (!seInfo) {
@@ -417,7 +525,7 @@
dvmAbort();
}
}
- StringObject* niceNameObj = (StringObject*)args[6];
+ StringObject* niceNameObj = (StringObject*)args[7];
if (niceNameObj) {
niceName = dvmCreateCstrFromString(niceNameObj);
if (!niceName) {
@@ -465,15 +573,30 @@
#endif /* HAVE_ANDROID_OS */
- err = setgroupsIntarray(gids);
+ if (mountMode != MOUNT_EXTERNAL_NONE) {
+ err = mountEmulatedStorage(uid, mountMode);
+ if (err < 0) {
+ ALOGE("cannot mountExternalStorage(): %s", strerror(errno));
+ if (errno == ENOTCONN || errno == EROFS) {
+ // When device is actively encrypting, we get ENOTCONN here
+ // since FUSE was mounted before the framework restarted.
+ // When encrypted device is booting, we get EROFS since
+ // FUSE hasn't been created yet by init.
+ // In either case, continue without external storage.
+ } else {
+ dvmAbort();
+ }
+ }
+ }
+
+ err = setgroupsIntarray(gids);
if (err < 0) {
ALOGE("cannot setgroups(): %s", strerror(errno));
dvmAbort();
}
err = setrlimitsFromArray(rlimits);
-
if (err < 0) {
ALOGE("cannot setrlimit(): %s", strerror(errno));
dvmAbort();
@@ -549,8 +672,10 @@
return pid;
}
-/* native public static int forkAndSpecialize(int uid, int gid,
- * int[] gids, int debugFlags, String seInfo, String niceName);
+/*
+ * native public static int nativeForkAndSpecialize(int uid, int gid,
+ * int[] gids, int debugFlags, int[][] rlimits, int mountExternal,
+ * String seInfo, String niceName);
*/
static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,
JValue* pResult)
@@ -562,9 +687,10 @@
RETURN_INT(pid);
}
-/* native public static int forkSystemServer(int uid, int gid,
- * int[] gids, int debugFlags, long permittedCapabilities,
- * long effectiveCapabilities);
+/*
+ * native public static int nativeForkSystemServer(int uid, int gid,
+ * int[] gids, int debugFlags, int[][] rlimits,
+ * long permittedCapabilities, long effectiveCapabilities);
*/
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
const u4* args, JValue* pResult)
@@ -609,7 +735,7 @@
const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
{ "nativeFork", "()I",
Dalvik_dalvik_system_Zygote_fork },
- { "nativeForkAndSpecialize", "(II[II[[ILjava/lang/String;Ljava/lang/String;)I",
+ { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I",
Dalvik_dalvik_system_Zygote_forkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
Dalvik_dalvik_system_Zygote_forkSystemServer },
diff --git a/vm/oo/Class.cpp b/vm/oo/Class.cpp
index eb816b0..85ac9a7 100644
--- a/vm/oo/Class.cpp
+++ b/vm/oo/Class.cpp
@@ -2914,25 +2914,29 @@
Method* superMeth = clazz->vtable[si];
if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0) {
- if (dvmCheckMethodAccess(clazz, superMeth)) {
- /* verify */
- if (dvmIsFinalMethod(superMeth)) {
- ALOGW("Method %s.%s overrides final %s.%s",
- localMeth->clazz->descriptor, localMeth->name,
- superMeth->clazz->descriptor, superMeth->name);
- goto bail;
- }
- clazz->vtable[si] = localMeth;
- localMeth->methodIndex = (u2) si;
- //ALOGV("+++ override %s.%s (slot %d)",
- // clazz->descriptor, localMeth->name, si);
- break;
- } else {
- ALOGW("in older versions of dalvik, method %s.%s would have incorrectly "
- "overridden package-private method with same name in %s",
+ // We should have an access check here, but some apps rely on us not
+ // checking access: http://b/7301030
+ bool isAccessible = dvmCheckMethodAccess(clazz, superMeth);
+ if (dvmIsFinalMethod(superMeth)) {
+ ALOGE("Method %s.%s overrides final %s.%s",
+ localMeth->clazz->descriptor, localMeth->name,
+ superMeth->clazz->descriptor, superMeth->name);
+ goto bail;
+ }
+
+ // Warn if we just spotted code relying on this bug...
+ if (!isAccessible) {
+ ALOGW("method %s.%s incorrectly overrides "
+ "package-private method with same name in %s",
localMeth->clazz->descriptor, localMeth->name,
superMeth->clazz->descriptor);
}
+
+ clazz->vtable[si] = localMeth;
+ localMeth->methodIndex = (u2) si;
+ //ALOGV("+++ override %s.%s (slot %d)",
+ // clazz->descriptor, localMeth->name, si);
+ break;
}
}
diff --git a/vm/reflect/Annotation.cpp b/vm/reflect/Annotation.cpp
index 453ddc5..26dea75 100644
--- a/vm/reflect/Annotation.cpp
+++ b/vm/reflect/Annotation.cpp
@@ -679,7 +679,7 @@
ALOGW("WARNING: could not find annotation member %s in %s",
name, annoClass->descriptor);
} else {
- methodObj = dvmCreateReflectMethodObject(annoMeth);
+ methodObj = dvmCreateReflectObjForMethod(annoClass, annoMeth);
methodReturn = dvmGetBoxedReturnType(annoMeth);
}
}