1306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom/* 2306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * Copyright (C) 2014 The Android Open Source Project 3306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * 4306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * you may not use this file except in compliance with the License. 6306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * You may obtain a copy of the License at 7306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * 8306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * 10306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 11306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * See the License for the specific language governing permissions and 14306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * limitations under the License. 15306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom */ 16306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 17306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstromimport java.lang.reflect.Method; 18306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstromimport java.nio.ByteBuffer; 19306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 20306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrompublic class Main { 21306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom public static void main(String[] args) throws Exception { 22306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom String name = System.getProperty("java.vm.name"); 23306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom if (!"Dalvik".equals(name)) { 24306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("This test is not supported on " + name); 25306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom return; 26306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 27306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom testRecentAllocationTracking(); 28306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 29306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 30306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom private static void testRecentAllocationTracking() throws Exception { 31306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("Confirm empty"); 32306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Allocations empty = new Allocations(DdmVmInternal.getRecentAllocations()); 33306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("empty=" + empty); 34306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 35306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("Confirm enable"); 36306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus()); 37306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom DdmVmInternal.enableRecentAllocations(true); 38306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus()); 39306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 40306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("Capture some allocations (note just this causes allocations)"); 41306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Allocations before = new Allocations(DdmVmInternal.getRecentAllocations()); 42306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("before > 0=" + (before.numberOfEntries > 0)); 43306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 44306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("Confirm when we overflow, we don't roll over to zero. b/17392248"); 45306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom final int overflowAllocations = 64 * 1024; // Won't fit in unsigned 16-bit value. 46306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom for (int i = 0; i < overflowAllocations; i++) { 471ed11b9ad5512cf464cb1686640df53201fa5297Man Cao new Object(); 48306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 49306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Allocations after = new Allocations(DdmVmInternal.getRecentAllocations()); 50306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("before < overflowAllocations=" + (before.numberOfEntries < overflowAllocations)); 51306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("after > before=" + (after.numberOfEntries > before.numberOfEntries)); 52306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("after.numberOfEntries=" + after.numberOfEntries); 53306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 54306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("Disable and confirm back to empty"); 55306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom DdmVmInternal.enableRecentAllocations(false); 56306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus()); 57306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Allocations reset = new Allocations(DdmVmInternal.getRecentAllocations()); 58306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("reset=" + reset); 59306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 60306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("Confirm we can disable twice in a row"); 61306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom DdmVmInternal.enableRecentAllocations(false); 62306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus()); 63306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom DdmVmInternal.enableRecentAllocations(false); 64306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus()); 65306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 66306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("Confirm we can reenable twice in a row without losing allocations"); 67306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom DdmVmInternal.enableRecentAllocations(true); 68306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus()); 691ed11b9ad5512cf464cb1686640df53201fa5297Man Cao for (int i = 0; i < 16 * 1024; i++) { 701ed11b9ad5512cf464cb1686640df53201fa5297Man Cao new String("fnord"); 71306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 72306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Allocations first = new Allocations(DdmVmInternal.getRecentAllocations()); 73306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom DdmVmInternal.enableRecentAllocations(true); 74306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus()); 75306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Allocations second = new Allocations(DdmVmInternal.getRecentAllocations()); 76306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("second > first =" + (second.numberOfEntries > first.numberOfEntries)); 77306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 78306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("Goodbye"); 79306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom DdmVmInternal.enableRecentAllocations(false); 80306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Allocations goodbye = new Allocations(DdmVmInternal.getRecentAllocations()); 81306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom System.out.println("goodbye=" + goodbye); 82306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 83306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 84306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom private static class Allocations { 85306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom final int messageHeaderLen; 86306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom final int entryHeaderLen; 87306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom final int stackFrameLen; 88306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom final int numberOfEntries; 89306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom final int offsetToStringTableFromStartOfMessage; 90306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom final int numberOfClassNameStrings; 91306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom final int numberOfMethodNameStrings; 92306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom final int numberOfSourceFileNameStrings; 93306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 94306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Allocations(byte[] allocations) { 95306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom ByteBuffer b = ByteBuffer.wrap(allocations); 96306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom messageHeaderLen = b.get() & 0xff; 97306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom if (messageHeaderLen != 15) { 98306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom throw new IllegalArgumentException("Unexpected messageHeaderLen " + messageHeaderLen); 99306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 100306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom entryHeaderLen = b.get() & 0xff; 101306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom if (entryHeaderLen != 9) { 102306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom throw new IllegalArgumentException("Unexpected entryHeaderLen " + entryHeaderLen); 103306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 104306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom stackFrameLen = b.get() & 0xff; 105306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom if (stackFrameLen != 8) { 106306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom throw new IllegalArgumentException("Unexpected messageHeaderLen " + stackFrameLen); 107306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 108306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom numberOfEntries = b.getShort() & 0xffff; 109306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom offsetToStringTableFromStartOfMessage = b.getInt(); 110306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom numberOfClassNameStrings = b.getShort() & 0xffff; 111306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom numberOfMethodNameStrings = b.getShort() & 0xffff; 112306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom numberOfSourceFileNameStrings = b.getShort() & 0xffff; 113306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 114306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 115306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom public String toString() { 116306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom return ("Allocations[message header len: " + messageHeaderLen + 117306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom " entry header len: " + entryHeaderLen + 118306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom " stack frame len: " + stackFrameLen + 119306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom " number of entries: " + numberOfEntries + 120306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom " offset to string table from start of message: " + offsetToStringTableFromStartOfMessage + 121306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom " number of class name strings: " + numberOfClassNameStrings + 122306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom " number of method name strings: " + numberOfMethodNameStrings + 123306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom " number of source file name strings: " + numberOfSourceFileNameStrings + 124306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom "]"); 125306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 126306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 127306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 128306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom private static class DdmVmInternal { 129306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom private static final Method enableRecentAllocationsMethod; 130306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom private static final Method getRecentAllocationStatusMethod; 131306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom private static final Method getRecentAllocationsMethod; 132306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom static { 133306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom try { 134306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Class c = Class.forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal"); 135306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom enableRecentAllocationsMethod = c.getDeclaredMethod("enableRecentAllocations", 136306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom Boolean.TYPE); 137306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom getRecentAllocationStatusMethod = c.getDeclaredMethod("getRecentAllocationStatus"); 138306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom getRecentAllocationsMethod = c.getDeclaredMethod("getRecentAllocations"); 139306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } catch (Exception e) { 140306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom throw new RuntimeException(e); 141306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 142306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 143306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom 144306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom public static void enableRecentAllocations(boolean enable) throws Exception { 145306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom enableRecentAllocationsMethod.invoke(null, enable); 146306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 147306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom public static boolean getRecentAllocationStatus() throws Exception { 148306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom return (boolean) getRecentAllocationStatusMethod.invoke(null); 149306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 150306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom public static byte[] getRecentAllocations() throws Exception { 151306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom return (byte[]) getRecentAllocationsMethod.invoke(null); 152306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 153306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom } 154306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom} 155