blob: 50bbe5178e1094b07a16678688deefbfbc60d7c1 [file] [log] [blame]
Brian Carlstrom306db812014-09-05 13:01:41 -07001/*
2 * Copyright (C) 2014 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
17import java.lang.reflect.Method;
18import java.nio.ByteBuffer;
19
20public class Main {
21 public static void main(String[] args) throws Exception {
22 String name = System.getProperty("java.vm.name");
23 if (!"Dalvik".equals(name)) {
24 System.out.println("This test is not supported on " + name);
25 return;
26 }
27 testRecentAllocationTracking();
28 }
29
30 private static void testRecentAllocationTracking() throws Exception {
31 System.out.println("Confirm empty");
32 Allocations empty = new Allocations(DdmVmInternal.getRecentAllocations());
33 System.out.println("empty=" + empty);
34
35 System.out.println("Confirm enable");
36 System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
37 DdmVmInternal.enableRecentAllocations(true);
38 System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
39
40 System.out.println("Capture some allocations (note just this causes allocations)");
41 Allocations before = new Allocations(DdmVmInternal.getRecentAllocations());
42 System.out.println("before > 0=" + (before.numberOfEntries > 0));
43
44 System.out.println("Confirm when we overflow, we don't roll over to zero. b/17392248");
45 final int overflowAllocations = 64 * 1024; // Won't fit in unsigned 16-bit value.
46 for (int i = 0; i < overflowAllocations; i++) {
Mingyao Yang062157f2016-03-02 10:15:36 -080047 new Object() {
48 // Add a finalizer so that the allocation won't be eliminated.
49 public void finalize() {
50 System.out.print("");
51 }
52 };
Brian Carlstrom306db812014-09-05 13:01:41 -070053 }
54 Allocations after = new Allocations(DdmVmInternal.getRecentAllocations());
55 System.out.println("before < overflowAllocations=" + (before.numberOfEntries < overflowAllocations));
56 System.out.println("after > before=" + (after.numberOfEntries > before.numberOfEntries));
57 System.out.println("after.numberOfEntries=" + after.numberOfEntries);
58
59 System.out.println("Disable and confirm back to empty");
60 DdmVmInternal.enableRecentAllocations(false);
61 System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
62 Allocations reset = new Allocations(DdmVmInternal.getRecentAllocations());
63 System.out.println("reset=" + reset);
64
65 System.out.println("Confirm we can disable twice in a row");
66 DdmVmInternal.enableRecentAllocations(false);
67 System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
68 DdmVmInternal.enableRecentAllocations(false);
69 System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
70
71 System.out.println("Confirm we can reenable twice in a row without losing allocations");
72 DdmVmInternal.enableRecentAllocations(true);
73 System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
Man Cao1ed11b92015-06-11 22:47:35 -070074 for (int i = 0; i < 16 * 1024; i++) {
75 new String("fnord");
Brian Carlstrom306db812014-09-05 13:01:41 -070076 }
77 Allocations first = new Allocations(DdmVmInternal.getRecentAllocations());
78 DdmVmInternal.enableRecentAllocations(true);
79 System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
80 Allocations second = new Allocations(DdmVmInternal.getRecentAllocations());
81 System.out.println("second > first =" + (second.numberOfEntries > first.numberOfEntries));
82
83 System.out.println("Goodbye");
84 DdmVmInternal.enableRecentAllocations(false);
85 Allocations goodbye = new Allocations(DdmVmInternal.getRecentAllocations());
86 System.out.println("goodbye=" + goodbye);
87 }
88
89 private static class Allocations {
90 final int messageHeaderLen;
91 final int entryHeaderLen;
92 final int stackFrameLen;
93 final int numberOfEntries;
94 final int offsetToStringTableFromStartOfMessage;
95 final int numberOfClassNameStrings;
96 final int numberOfMethodNameStrings;
97 final int numberOfSourceFileNameStrings;
98
99 Allocations(byte[] allocations) {
100 ByteBuffer b = ByteBuffer.wrap(allocations);
101 messageHeaderLen = b.get() & 0xff;
102 if (messageHeaderLen != 15) {
103 throw new IllegalArgumentException("Unexpected messageHeaderLen " + messageHeaderLen);
104 }
105 entryHeaderLen = b.get() & 0xff;
106 if (entryHeaderLen != 9) {
107 throw new IllegalArgumentException("Unexpected entryHeaderLen " + entryHeaderLen);
108 }
109 stackFrameLen = b.get() & 0xff;
110 if (stackFrameLen != 8) {
111 throw new IllegalArgumentException("Unexpected messageHeaderLen " + stackFrameLen);
112 }
113 numberOfEntries = b.getShort() & 0xffff;
114 offsetToStringTableFromStartOfMessage = b.getInt();
115 numberOfClassNameStrings = b.getShort() & 0xffff;
116 numberOfMethodNameStrings = b.getShort() & 0xffff;
117 numberOfSourceFileNameStrings = b.getShort() & 0xffff;
118 }
119
120 public String toString() {
121 return ("Allocations[message header len: " + messageHeaderLen +
122 " entry header len: " + entryHeaderLen +
123 " stack frame len: " + stackFrameLen +
124 " number of entries: " + numberOfEntries +
125 " offset to string table from start of message: " + offsetToStringTableFromStartOfMessage +
126 " number of class name strings: " + numberOfClassNameStrings +
127 " number of method name strings: " + numberOfMethodNameStrings +
128 " number of source file name strings: " + numberOfSourceFileNameStrings +
129 "]");
130 }
131 }
132
133 private static class DdmVmInternal {
134 private static final Method enableRecentAllocationsMethod;
135 private static final Method getRecentAllocationStatusMethod;
136 private static final Method getRecentAllocationsMethod;
137 static {
138 try {
139 Class c = Class.forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal");
140 enableRecentAllocationsMethod = c.getDeclaredMethod("enableRecentAllocations",
141 Boolean.TYPE);
142 getRecentAllocationStatusMethod = c.getDeclaredMethod("getRecentAllocationStatus");
143 getRecentAllocationsMethod = c.getDeclaredMethod("getRecentAllocations");
144 } catch (Exception e) {
145 throw new RuntimeException(e);
146 }
147 }
148
149 public static void enableRecentAllocations(boolean enable) throws Exception {
150 enableRecentAllocationsMethod.invoke(null, enable);
151 }
152 public static boolean getRecentAllocationStatus() throws Exception {
153 return (boolean) getRecentAllocationStatusMethod.invoke(null);
154 }
155 public static byte[] getRecentAllocations() throws Exception {
156 return (byte[]) getRecentAllocationsMethod.invoke(null);
157 }
158 }
159}