summaryrefslogtreecommitdiffstats
path: root/test/098-ddmc/src
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2014-09-05 13:01:41 -0700
committerBrian Carlstrom <bdc@google.com>2014-09-05 13:24:24 -0700
commit306db81aba41eb244a4e8299cf58ac18ae9999c7 (patch)
treea069a9dda1b246466cbeee2736f46f18ef56714e /test/098-ddmc/src
parentb14339904c9cacc4af74260c7325e4eb32947f95 (diff)
downloadart-306db81aba41eb244a4e8299cf58ac18ae9999c7.zip
art-306db81aba41eb244a4e8299cf58ac18ae9999c7.tar.gz
art-306db81aba41eb244a4e8299cf58ac18ae9999c7.tar.bz2
Fix numerous issues with DdmVmInternal allocation tracking
Issues addressed: - Using without JDWP attached caused native crash. - When buffer is full (64k entries), number of entries reported was 0. - Disabling tracking after disabling tracking caused native crash. - Asking for allocations after disabled caused native crash. - Lock ordering issues between mutator lock and alloc tracker lock. Adding 098-ddmc test to cover these cases. Bug: 17392248 (cherry picked from commit a5815065ac0877add9c0db3605d27b4d6c426e61) Change-Id: Ib0bc18dfcdafcc050ab9dceed3d167dd878d1d7a
Diffstat (limited to 'test/098-ddmc/src')
-rw-r--r--test/098-ddmc/src/Main.java154
1 files changed, 154 insertions, 0 deletions
diff --git a/test/098-ddmc/src/Main.java b/test/098-ddmc/src/Main.java
new file mode 100644
index 0000000..962bd7f
--- /dev/null
+++ b/test/098-ddmc/src/Main.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ String name = System.getProperty("java.vm.name");
+ if (!"Dalvik".equals(name)) {
+ System.out.println("This test is not supported on " + name);
+ return;
+ }
+ testRecentAllocationTracking();
+ }
+
+ private static void testRecentAllocationTracking() throws Exception {
+ System.out.println("Confirm empty");
+ Allocations empty = new Allocations(DdmVmInternal.getRecentAllocations());
+ System.out.println("empty=" + empty);
+
+ System.out.println("Confirm enable");
+ System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
+ DdmVmInternal.enableRecentAllocations(true);
+ System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
+
+ System.out.println("Capture some allocations (note just this causes allocations)");
+ Allocations before = new Allocations(DdmVmInternal.getRecentAllocations());
+ System.out.println("before > 0=" + (before.numberOfEntries > 0));
+
+ System.out.println("Confirm when we overflow, we don't roll over to zero. b/17392248");
+ final int overflowAllocations = 64 * 1024; // Won't fit in unsigned 16-bit value.
+ for (int i = 0; i < overflowAllocations; i++) {
+ new String("fnord");
+ }
+ Allocations after = new Allocations(DdmVmInternal.getRecentAllocations());
+ System.out.println("before < overflowAllocations=" + (before.numberOfEntries < overflowAllocations));
+ System.out.println("after > before=" + (after.numberOfEntries > before.numberOfEntries));
+ System.out.println("after.numberOfEntries=" + after.numberOfEntries);
+
+ System.out.println("Disable and confirm back to empty");
+ DdmVmInternal.enableRecentAllocations(false);
+ System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
+ Allocations reset = new Allocations(DdmVmInternal.getRecentAllocations());
+ System.out.println("reset=" + reset);
+
+ System.out.println("Confirm we can disable twice in a row");
+ DdmVmInternal.enableRecentAllocations(false);
+ System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
+ DdmVmInternal.enableRecentAllocations(false);
+ System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
+
+ System.out.println("Confirm we can reenable twice in a row without losing allocations");
+ DdmVmInternal.enableRecentAllocations(true);
+ System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
+ for (int i = 0; i < 16 * 1024; i++) {
+ new String("fnord");
+ }
+ Allocations first = new Allocations(DdmVmInternal.getRecentAllocations());
+ DdmVmInternal.enableRecentAllocations(true);
+ System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
+ Allocations second = new Allocations(DdmVmInternal.getRecentAllocations());
+ System.out.println("second > first =" + (second.numberOfEntries > first.numberOfEntries));
+
+ System.out.println("Goodbye");
+ DdmVmInternal.enableRecentAllocations(false);
+ Allocations goodbye = new Allocations(DdmVmInternal.getRecentAllocations());
+ System.out.println("goodbye=" + goodbye);
+ }
+
+ private static class Allocations {
+ final int messageHeaderLen;
+ final int entryHeaderLen;
+ final int stackFrameLen;
+ final int numberOfEntries;
+ final int offsetToStringTableFromStartOfMessage;
+ final int numberOfClassNameStrings;
+ final int numberOfMethodNameStrings;
+ final int numberOfSourceFileNameStrings;
+
+ Allocations(byte[] allocations) {
+ ByteBuffer b = ByteBuffer.wrap(allocations);
+ messageHeaderLen = b.get() & 0xff;
+ if (messageHeaderLen != 15) {
+ throw new IllegalArgumentException("Unexpected messageHeaderLen " + messageHeaderLen);
+ }
+ entryHeaderLen = b.get() & 0xff;
+ if (entryHeaderLen != 9) {
+ throw new IllegalArgumentException("Unexpected entryHeaderLen " + entryHeaderLen);
+ }
+ stackFrameLen = b.get() & 0xff;
+ if (stackFrameLen != 8) {
+ throw new IllegalArgumentException("Unexpected messageHeaderLen " + stackFrameLen);
+ }
+ numberOfEntries = b.getShort() & 0xffff;
+ offsetToStringTableFromStartOfMessage = b.getInt();
+ numberOfClassNameStrings = b.getShort() & 0xffff;
+ numberOfMethodNameStrings = b.getShort() & 0xffff;
+ numberOfSourceFileNameStrings = b.getShort() & 0xffff;
+ }
+
+ public String toString() {
+ return ("Allocations[message header len: " + messageHeaderLen +
+ " entry header len: " + entryHeaderLen +
+ " stack frame len: " + stackFrameLen +
+ " number of entries: " + numberOfEntries +
+ " offset to string table from start of message: " + offsetToStringTableFromStartOfMessage +
+ " number of class name strings: " + numberOfClassNameStrings +
+ " number of method name strings: " + numberOfMethodNameStrings +
+ " number of source file name strings: " + numberOfSourceFileNameStrings +
+ "]");
+ }
+ }
+
+ private static class DdmVmInternal {
+ private static final Method enableRecentAllocationsMethod;
+ private static final Method getRecentAllocationStatusMethod;
+ private static final Method getRecentAllocationsMethod;
+ static {
+ try {
+ Class c = Class.forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal");
+ enableRecentAllocationsMethod = c.getDeclaredMethod("enableRecentAllocations",
+ Boolean.TYPE);
+ getRecentAllocationStatusMethod = c.getDeclaredMethod("getRecentAllocationStatus");
+ getRecentAllocationsMethod = c.getDeclaredMethod("getRecentAllocations");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void enableRecentAllocations(boolean enable) throws Exception {
+ enableRecentAllocationsMethod.invoke(null, enable);
+ }
+ public static boolean getRecentAllocationStatus() throws Exception {
+ return (boolean) getRecentAllocationStatusMethod.invoke(null);
+ }
+ public static byte[] getRecentAllocations() throws Exception {
+ return (byte[]) getRecentAllocationsMethod.invoke(null);
+ }
+ }
+}