android_os_Debug.cpp revision 393b84c137fe52f42205cef7e63b7a04b4bfd789
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define LOG_TAG "android.os.Debug" 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/misc.h" 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <time.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/time.h> 2806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <errno.h> 2906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <assert.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <malloc.h> 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID dalvikPss_field; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID dalvikPrivateDirty_field; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID dalvikSharedDirty_field; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID nativePss_field; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID nativePrivateDirty_field; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID nativeSharedDirty_field; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID otherPss_field; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID otherPrivateDirty_field; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID otherSharedDirty_field; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct stats_t { 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dalvikPss; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dalvikPrivateDirty; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dalvikSharedDirty; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nativePss; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nativePrivateDirty; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nativeSharedDirty; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int otherPss; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int otherPrivateDirty; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int otherSharedDirty; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BINDER_STATS "/proc/binder/stats" 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapSize(JNIEnv *env, jobject clazz) 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct mallinfo info = mallinfo(); 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jlong) info.usmblks; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapAllocatedSize(JNIEnv *env, jobject clazz) 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct mallinfo info = mallinfo(); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jlong) info.uordblks; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz) 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct mallinfo info = mallinfo(); 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jlong) info.fordblks; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void read_mapinfo(FILE *fp, stats_t* stats) 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char line[1024]; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool skip, done = false; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned start = 0, size = 0, resident = 0, pss = 0; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned shared_clean = 0, shared_dirty = 0; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned private_clean = 0, private_dirty = 0; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned referenced = 0; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned temp; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int isNativeHeap; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int isDalvikHeap; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int isSqliteHeap; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(fgets(line, 1024, fp) == 0) return; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!done) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isNativeHeap = 0; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isDalvikHeap = 0; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isSqliteHeap = 0; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skip = false; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len = strlen(line); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len < 1) return; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project line[--len] = 0; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* ignore guard pages */ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len > 18 && line[17] == '-') skip = true; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start = strtoul(line, 0, 16); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strstr(line, "[heap]")) { 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isNativeHeap = 1; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (strstr(line, "/dalvik-LinearAlloc")) { 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isDalvikHeap = 1; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (strstr(line, "/mspace/dalvik-heap")) { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isDalvikHeap = 1; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (strstr(line, "/dalvik-heap-bitmap/")) { 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isDalvikHeap = 1; 135bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba } else if (strstr(line, "/data/dalvik-cache/")) { 136bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba isDalvikHeap = 1; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (strstr(line, "/tmp/sqlite-heap")) { 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isSqliteHeap = 1; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //LOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap, 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // isSqliteHeap, line); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fgets(line, 1024, fp) == 0) { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project done = true; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sscanf(line, "Size: %d kB", &temp) == 1) { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size = temp; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Rss: %d kB", &temp) == 1) { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resident = temp; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Pss: %d kB", &temp) == 1) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pss = temp; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Shared_Clean: %d kB", &temp) == 1) { 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project shared_clean = temp; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) { 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project shared_dirty = temp; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Private_Clean: %d kB", &temp) == 1) { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private_clean = temp; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Private_Dirty: %d kB", &temp) == 1) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private_dirty = temp; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Referenced: %d kB", &temp) == 1) { 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project referenced = temp; 166bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba } else if (strlen(line) > 30 && line[8] == '-' && line[17] == ' ') { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // looks like a new mapping 168bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba // example: "10000000-10001000 ---p 10000000 00:00 0" 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!skip) { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isNativeHeap) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stats->nativePss += pss; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stats->nativePrivateDirty += private_dirty; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stats->nativeSharedDirty += shared_dirty; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (isDalvikHeap) { 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stats->dalvikPss += pss; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stats->dalvikPrivateDirty += private_dirty; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stats->dalvikSharedDirty += shared_dirty; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if ( isSqliteHeap) { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ignore 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stats->otherPss += pss; 186bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba stats->otherPrivateDirty += private_dirty; 187bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba stats->otherSharedDirty += shared_dirty; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void load_maps(int pid, stats_t* stats) 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char tmp[128]; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FILE *fp; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(tmp, "/proc/%d/smaps", pid); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fp = fopen(tmp, "r"); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fp == 0) return; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project read_mapinfo(fp, stats); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fclose(fp); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2063025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz, 2073025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn jint pid, jobject object) 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stats_t stats; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&stats, 0, sizeof(stats_t)); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2123025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn load_maps(pid, &stats); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, dalvikPss_field, stats.dalvikPss); 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, dalvikPrivateDirty_field, stats.dalvikPrivateDirty); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, dalvikSharedDirty_field, stats.dalvikSharedDirty); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, nativePss_field, stats.nativePss); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, nativePrivateDirty_field, stats.nativePrivateDirty); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, nativeSharedDirty_field, stats.nativeSharedDirty); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, otherPss_field, stats.otherPss); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, otherPrivateDirty_field, stats.otherPrivateDirty); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, otherSharedDirty_field, stats.otherSharedDirty); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2273025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object) 2283025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn{ 2293025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object); 2303025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn} 2313025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint read_binder_stat(const char* stat) 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FILE* fp = fopen(BINDER_STATS, "r"); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fp == NULL) { 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char line[1024]; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char compare[128]; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = snprintf(compare, 128, "proc %d", getpid()); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // loop until we have the block that represents this process 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fgets(line, 1024, fp) == 0) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (strncmp(compare, line, len)); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // now that we have this process, read until we find the stat that we are looking for 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len = snprintf(compare, 128, " %s: ", stat); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fgets(line, 1024, fp) == 0) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (strncmp(compare, line, len)); 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we have the line, now increment the line ptr to the value 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char* ptr = line + len; 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return atoi(ptr); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_Debug_getBinderSentTransactions(JNIEnv *env, jobject clazz) 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return read_binder_stat("bcTRANSACTION"); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_getBinderReceivedTransactions(JNIEnv *env, jobject clazz) 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return read_binder_stat("brTRANSACTION"); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// these are implemented in android_util_Binder.cpp 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 28106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#ifdef HAVE_ANDROID_OS 28206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* pulled out of bionic */ 28306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, 28406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); 28506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void free_malloc_leak_info(uint8_t* info); 28606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define SIZE_FLAG_ZYGOTE_CHILD (1<<31) 28706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define BACKTRACE_SIZE 32 28806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 28906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* 29006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * This is a qsort() callback. 29106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * 29206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * See dumpNativeHeap() for comments about the data format and sort order. 29306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */ 29406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic int compareHeapRecords(const void* vrec1, const void* vrec2) 29506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{ 29606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden const size_t* rec1 = (const size_t*) vrec1; 29706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden const size_t* rec2 = (const size_t*) vrec2; 29806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t size1 = *rec1; 29906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t size2 = *rec2; 30006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 30106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (size1 < size2) { 30206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return 1; 30306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } else if (size1 > size2) { 30406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return -1; 30506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 30606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 30706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t* bt1 = (intptr_t*)(rec1 + 2); 30806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t* bt2 = (intptr_t*)(rec2 + 2); 30906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden for (size_t idx = 0; idx < BACKTRACE_SIZE; idx++) { 31006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t addr1 = bt1[idx]; 31106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t addr2 = bt2[idx]; 31206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (addr1 == addr2) { 31306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (addr1 == 0) 31406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden break; 31506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden continue; 31606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 31706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (addr1 < addr2) { 31806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return -1; 31906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } else if (addr1 > addr2) { 32006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return 1; 32106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 32206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 32306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 32406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return 0; 32506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden} 32606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 32706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* 32806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The get_malloc_leak_info() call returns an array of structs that 32906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * look like this: 33006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * 33106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * size_t size 33206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * size_t allocations 33306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * intptr_t backtrace[32] 33406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * 33506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * "size" is the size of the allocation, "backtrace" is a fixed-size 33606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * array of function pointers, and "allocations" is the number of 33706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * allocations with the exact same size and backtrace. 33806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * 33906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The entries are sorted by descending total size (i.e. size*allocations) 34006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * then allocation count. For best results with "diff" we'd like to sort 34106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * primarily by individual size then stack trace. Since the entries are 34206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * fixed-size, and we're allowed (by the current implementation) to mangle 34306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * them, we can do this in place. 34406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */ 34506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void dumpNativeHeap(FILE* fp) 34606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{ 34706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden uint8_t* info = NULL; 34806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t overallSize, infoSize, totalMemory, backtraceSize; 34906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 35006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, 35106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden &backtraceSize); 35206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (info == NULL) { 35306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "Native heap dump not available. To enable, run these" 35406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden " commands (requires root):\n"); 35506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "$ adb shell setprop libc.debug.malloc 1\n"); 35606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "$ adb shell stop\n"); 35706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "$ adb shell start\n"); 35806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 35906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 36006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden assert(infoSize != 0); 36106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden assert(overallSize % infoSize == 0); 36206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 36306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "Android Native Heap Dump v1.0\n\n"); 36406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 36506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t recordCount = overallSize / infoSize; 36606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "Total memory: %zu\n", totalMemory); 36706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "Allocation records: %zd\n", recordCount); 36806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (backtraceSize != BACKTRACE_SIZE) { 36906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "WARNING: mismatched backtrace sizes (%d vs. %d)\n", 37006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden backtraceSize, BACKTRACE_SIZE); 37106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 37206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "\n"); 37306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 37406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden /* re-sort the entries */ 37506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden qsort(info, recordCount, infoSize, compareHeapRecords); 37606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 37706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden /* dump the entries to the file */ 37806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden const uint8_t* ptr = info; 37906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden for (size_t idx = 0; idx < recordCount; idx++) { 38006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t size = *(size_t*) ptr; 38106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t allocations = *(size_t*) (ptr + sizeof(size_t)); 38206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t* backtrace = (intptr_t*) (ptr + sizeof(size_t) * 2); 38306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 38406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "z %d sz %8zu num %4zu bt", 38506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden (size & SIZE_FLAG_ZYGOTE_CHILD) != 0, 38606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size & ~SIZE_FLAG_ZYGOTE_CHILD, 38706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden allocations); 38806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden for (size_t bt = 0; bt < backtraceSize; bt++) { 38906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (backtrace[bt] == 0) { 39006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden break; 39106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } else { 39206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, " %08x", backtrace[bt]); 39306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 39406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 39506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "\n"); 39606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 39706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden ptr += infoSize; 39806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 39906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 40006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden free_malloc_leak_info(info); 401393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom 402393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fprintf(fp, "MAPS\n"); 403393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom const char* maps = "/proc/self/maps"; 404393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom FILE* in = fopen(maps, "r"); 405393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom if (in == NULL) { 406393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fprintf(fp, "Could not open %s\n", maps); 407393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom return; 408393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom } 409393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom char buf[BUFSIZ]; 410393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom while (size_t n = fread(buf, sizeof(char), BUFSIZ, in)) { 411393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fwrite(buf, sizeof(char), n, fp); 412393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom } 413393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fclose(in); 414393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom 415393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fprintf(fp, "END\n"); 41606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden} 41706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#endif /*HAVE_ANDROID_OS*/ 41806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 41906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* 42006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * Dump the native heap, writing human-readable output to the specified 42106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * file descriptor. 42206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */ 42306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz, 42406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jobject fileDescriptor) 42506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{ 42606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (fileDescriptor == NULL) { 42706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jniThrowNullPointerException(env, NULL); 42806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 42906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 43006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden int origFd = jniGetFDFromFileDescriptor(env, fileDescriptor); 43106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (origFd < 0) { 43206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jniThrowRuntimeException(env, "Invalid file descriptor"); 43306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 43406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 43506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 43606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden /* dup() the descriptor so we don't close the original with fclose() */ 43706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden int fd = dup(origFd); 43806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (fd < 0) { 43906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden LOGW("dup(%d) failed: %s\n", origFd, strerror(errno)); 44006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jniThrowRuntimeException(env, "dup() failed"); 44106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 44206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 44306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 44406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden FILE* fp = fdopen(fd, "w"); 44506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (fp == NULL) { 44606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden LOGW("fdopen(%d) failed: %s\n", fd, strerror(errno)); 44706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden close(fd); 44806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jniThrowRuntimeException(env, "fdopen() failed"); 44906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 45006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 45106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 45206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#ifdef HAVE_ANDROID_OS 45306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden LOGD("Native heap dump starting...\n"); 45406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden dumpNativeHeap(fp); 45506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden LOGD("Native heap dump complete.\n"); 45606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#else 45706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "Native heap dump not available on this platform\n"); 45806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#endif 45906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 46006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fclose(fp); 46106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden} 46206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 46306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration. 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = { 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getNativeHeapSize", "()J", 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getNativeHeapSize }, 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getNativeHeapAllocatedSize", "()J", 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getNativeHeapAllocatedSize }, 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getNativeHeapFreeSize", "()J", 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getNativeHeapFreeSize }, 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getMemoryInfo", "(Landroid/os/Debug$MemoryInfo;)V", 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getDirtyPages }, 4773025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn { "getMemoryInfo", "(ILandroid/os/Debug$MemoryInfo;)V", 4783025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn (void*) android_os_Debug_getDirtyPagesPid }, 47906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden { "dumpNativeHeap", "(Ljava/io/FileDescriptor;)V", 48006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden (void*) android_os_Debug_dumpNativeHeap }, 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderSentTransactions", "()I", 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getBinderSentTransactions }, 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderReceivedTransactions", "()I", 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_getBinderReceivedTransactions }, 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderLocalObjectCount", "()I", 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)android_os_Debug_getLocalObjectCount }, 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderProxyObjectCount", "()I", 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)android_os_Debug_getProxyObjectCount }, 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderDeathObjectCount", "()I", 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)android_os_Debug_getDeathObjectCount }, 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_os_Debug(JNIEnv *env) 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz = env->FindClass("android/os/Debug$MemoryInfo"); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dalvikPss_field = env->GetFieldID(clazz, "dalvikPss", "I"); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dalvikPrivateDirty_field = env->GetFieldID(clazz, "dalvikPrivateDirty", "I"); 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dalvikSharedDirty_field = env->GetFieldID(clazz, "dalvikSharedDirty", "I"); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nativePss_field = env->GetFieldID(clazz, "nativePss", "I"); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nativePrivateDirty_field = env->GetFieldID(clazz, "nativePrivateDirty", "I"); 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nativeSharedDirty_field = env->GetFieldID(clazz, "nativeSharedDirty", "I"); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project otherPss_field = env->GetFieldID(clazz, "otherPss", "I"); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project otherPrivateDirty_field = env->GetFieldID(clazz, "otherPrivateDirty", "I"); 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project otherSharedDirty_field = env->GetFieldID(clazz, "otherSharedDirty", "I"); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods)); 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 51206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}; // namespace android 513