├── .gitignore ├── DuplicatedBitmapAnalyzer ├── .gitignore ├── build.gradle └── src │ └── com │ └── hprof │ └── bitmap │ └── Main.java ├── README.md ├── build.gradle ├── doc ├── 4e2b2a183d1b48bcf2b12af45afdbc12.png ├── Help - Eclipse Platform.htm └── manual.html ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── tools └── DuplicatedBitmapAnalyzer-1.0.jar /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .DS_Store 5 | **/build/ 6 | /captures 7 | **/.externalNativeBuild/ 8 | .idea/ 9 | -------------------------------------------------------------------------------- /DuplicatedBitmapAnalyzer/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /tools_output -------------------------------------------------------------------------------- /DuplicatedBitmapAnalyzer/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | 4 | 5 | version 1.0 6 | 7 | dependencies { 8 | implementation fileTree(include: ['*.jar'], dir: 'libs') 9 | } 10 | 11 | 12 | jar { 13 | manifest { 14 | attributes 'Main-Class': 'com.hprof.bitmap.Main' 15 | attributes 'Manifest-Version': version 16 | } 17 | 18 | from { 19 | exclude 'META-INF/MANIFEST.MF' 20 | exclude 'META-INF/*.SF' 21 | exclude 'META-INF/*.DSA' 22 | exclude 'META-INF/*.RSA' 23 | configurations.runtime.resolve().collect { 24 | it.isDirectory() ? it : zipTree(it) 25 | } 26 | } 27 | } 28 | 29 | // copy the jar to work directory 30 | task buildAlloctrackJar(type: Copy, dependsOn: [build, jar]) { 31 | group = "buildTool" 32 | from('build/libs') { 33 | include '*.jar' 34 | exclude '*-javadoc.jar' 35 | exclude '*-sources.jar' 36 | } 37 | into(rootProject.file("tools")) 38 | } 39 | -------------------------------------------------------------------------------- /DuplicatedBitmapAnalyzer/src/com/hprof/bitmap/Main.java: -------------------------------------------------------------------------------- 1 | package com.hprof.bitmap; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.IOException; 5 | import java.nio.ByteBuffer; 6 | import java.nio.channels.FileChannel; 7 | import java.util.ArrayList; 8 | 9 | public class Main { 10 | 11 | public static void main(String[] args) throws IOException { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chapter04 2 | 终于迎来了第一个课后作业,今天我们尝试通过分析内存文件hprof快速判断内存中是否存在重复的图片,并且将这些重复图片的PNG、堆栈等信息输出。 3 | 4 | hprof文件格式可以参考doc西面的manual.html文件 5 | 6 | **需要注意的是需要使用8.0以下的机器,因为8.0以后Bitmap中的buffer已经放到native内存中了** 7 | 8 | 下面是一个结果的样例: 9 | ``` 10 | "duplcateCount":2, 11 | "stacks":[ 12 | [ 13 | "static com.sample.launcher.controller.LauncherController mLauncherView(0x1349c400)", 14 | "com.sample.launcher.view.LauncherView mHeaderView(0x1349bc00)", 15 | "com.sample.homepage.header.HomePageHeaderView mSearchAndAddressBar(0x13118c00)", 16 | "android.widget.ImageView mDrawable(0x131f9400)", 17 | "android.graphics.drawable.BitmapDrawable mBitmapState(0x13799b80)", 18 | "android.graphics.drawable.BitmapDrawable$BitmapState mBitmap(0x13b0f4d8)", 19 | "android.graphics.Bitmap instance" 20 | ], 21 | [ 22 | "static com.sample.resources.ResourceCache cachePool(0x12d32380)", 23 | "com.sample.resources.ResourceCache table(0x12c30250)", 24 | "array java.util.HashMap$HashMapEntry[] [130](0x14724000)", 25 | "java.util.LinkedHashMap$LinkedHashMapEntry after(0x130ed420)", 26 | "java.util.LinkedHashMap$LinkedHashMapEntry value(0x1361f780)", 27 | "com.sample.resources.ResourceCache$CacheSoftReference T(0x1361f760)", 28 | "android.graphics.drawable.BitmapDrawable mBitmapState(0x136a2d30)", 29 | "android.graphics.drawable.BitmapDrawable$BitmapState mBitmap(0x13971708)", 30 | "android.graphics.Bitmap instance" 31 | ] 32 | ], 33 | "bufferHash":"4e2b2a183d1b48bcf2b12af45afdbc12", 34 | "width":60, 35 | "height":60, 36 | "bufferSize":14400 37 | ``` 38 | 39 | bufferHash对应的重复图片: 40 | 41 | ![](doc/4e2b2a183d1b48bcf2b12af45afdbc12.png) 42 | 43 | 44 | 实现提示 45 | ==== 46 | hprof文件分析我们有两个实现方法: 47 | 48 | 1. 参考 Android Profiler 中[perflib](https://android.googlesource.com/platform/tools/base/+/studio-master-dev/perflib/src/main/java/com/android/tools/perflib)的分析源码,其中重复Bitmap的代码是[DuplicatedBitmapAnalyzerTask](https://android.googlesource.com/platform/tools/base/+/studio-master-dev/perflib/src/main/java/com/android/tools/perflib/heap/memoryanalyzer/DuplicatedBitmapAnalyzerTask.java)。 49 | 2. 我们也可以使用 sqaure 的[HAHA](https://github.com/square/haha)库,其中核心方法为: 50 | 51 | ``` 52 | // 打开hprof文件 53 | final HeapSnapshot heapSnapshot = new HeapSnapshot(hprofFile); 54 | // 获得snapshot 55 | final Snapshot snapshot = heapSnapshot.getSnapshot(); 56 | // 获得Bitmap Class 57 | final ClassObj bitmapClass = snapshot.findClass("android.graphics.Bitmap"); 58 | // 获得heap, 只需要分析app和default heap即可 59 | Heap heap = snapshot.getHeaps(); 60 | // 从heap中获得所有的Bitmap实例 61 | final List bitmapInstances = bitmapClass.getHeapInstances(heap.getId()); 62 | // 从Bitmap实例中获得buffer数组 63 | ArrayInstance buffer = HahaHelper.fieldValue(((ClassInstance) bitmapInstance).getValues(), "mBuffer"); 64 | ``` 65 | 66 | 整个思路就是通过"mBuffer"的hash值判断哪些Bitmap是重复的。 67 | 68 | 提交方法 69 | ==== 70 | 整个提交方法如下: 71 | 72 | 1. 完善DuplicatedBitmapAnalyzer项目 73 | 2. 注明极客时间的账号 + 实现原理与心得体会 74 | 3. 发送pull request 到本repo 75 | 76 | 奖励 77 | === 78 | 根据项目质量和提交pull request的时间,抽取部分同学送上经典书籍。 79 | 80 | 最终结果也会在极客时间和repo中公布,欢迎大家积极参与! -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter() 7 | 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.2.0' 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | jcenter() 21 | 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /doc/4e2b2a183d1b48bcf2b12af45afdbc12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndroidAdvanceWithGeektime/Chapter04/840fb9cda4102bdd5bb5c651ba580427821edceb/doc/4e2b2a183d1b48bcf2b12af45afdbc12.png -------------------------------------------------------------------------------- /doc/Help - Eclipse Platform.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | Help - Eclipse Platform 9 | 10 | 11 | 12 | 28 | 29 | 30 | 35 | 36 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |

关闭提示 关闭

确 认 取 消
61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /doc/manual.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | HPROF Agent 9 | 10 | 11 | 13 |

HPROF 15 | Agent
16 |

17 |

Contents

18 | 19 |
    20 |
  1. HPROF 21 | Agent 22 |
      23 |
    1. Contents
    2. 24 |
    3. Overview
    4. 25 |
    5. Start-up
    6. 26 |
    7. Heap Allocation 27 | Profiles (heap=sites)
    8. 28 |
    9. Heap Dump (heap=dump)
    10. 29 |
    11. CPU Usage Sampling 30 | Profiles (cpu=samples)
    12. 31 |
    13. CPU Usage Times Profile (cpu=times) 32 |
    14. 33 |
    15. Binary Dump Format 34 | (format=b) 35 |
        36 |
      1. Socket Connection and 37 | Communication
      2. 38 |
      39 |
        40 |
      1. Handling of Arrays
      2. 41 |
      42 |
    16. 43 |
    17. Source Code
    18. 44 |
    45 |
  2. 46 |
47 | 48 |

Overview

49 |

This document describes the JVM TI Agent HPROF delivered in 50 | the Java Development Kit (JDK). It is intended as demonstration code 51 | for JVM TI, and as a functional 52 | replacement for the older HPROF JVMPI Agent delivered in past releases.
53 |

54 | Previous 1.4 and earlier releases of the JDK contained an HPROF 55 | agent built on the experimental JVMPI.  56 | The newer JVM TI replaces both JVMDI and JVMPI.   57 |

Note: Differences between 58 | this HPROF implementation and the older JVMPI based HPROF are marked in 59 | RED ITALICS 60 | throughout this document.
61 |

62 |
63 |

Start-up

64 |

HPROF is a simple profiler agent shipped with the JDK. It is 65 | a dynamically-linked 66 | library that interacts with the JVM TI and 67 | writes out profiling 68 | information either to a file or to a socket in ascii or binary format. 69 | This information can 70 | be further processed by a profiler front-end tool.

71 |

It is capable of presenting CPU usage, heap allocation statistics 72 | and monitor contention 73 | profiles. In addition it can also report complete heap dumps and states 74 | of all the monitors and threads in the Java virtual machine. 75 |

76 |

HPROF can be invoked by: 77 |

78 |
java -agentlib:hprof ToBeProfiledClass
79 | Depending on the type of profiling requested, HPROF instructs the 80 | virtual machine to send it the relevant JVM TI events and processes 81 | the event data into profiling information. For example, the following 82 | command obtains the heap allocation profile: 83 |
java -agentlib:hprof=heap=sites ToBeProfiledClass
84 | Following is the complete list of options that can passed to hprof : 85 |
86 |
java -agentlib:hprof=help

HPROF: Heap and CPU Profiling Agent (JVMTI Demonstration Code)

hprof usage: java -agentlib:hprof=[help]|[<option>=<value>, ...]

Option Name and Value Description Default
--------------------- ----------- -------
heap=dump|sites|all heap profiling all
cpu=samples|times|old CPU usage off
monitor=y|n monitor contention n
format=a|b text(txt) or binary output a
file=<file> write data to file java.hprof[{.txt}]
net=<host>:<port> send data over a socket off
depth=<size> stack trace depth 4
interval=<ms> sample interval in ms 10
cutoff=<value> output cutoff point 0.0001
lineno=y|n line number in traces? y
thread=y|n thread in traces? n
doe=y|n dump on exit? y
msa=y|n Solaris micro state accounting n
force=y|n force output to <file> y
verbose=y|n print messages about dumps y

Obsolete Options
----------------
gc_okay=y|n

Examples
--------
- Get sample cpu information every 20 millisec, with a stack depth of 3:
java -agentlib:hprof=cpu=samples,interval=20,depth=3 classname
- Get heap usage information based on the allocation sites:
java -agentlib:hprof=heap=sites classname

Notes
-----
- The option format=b cannot be used with monitor=y.
- The option format=b cannot be used with cpu=old|times.
- Use of the -Xrunhprof interface can still be used, e.g.
java -Xrunhprof:[help]|[<option>=<value>, ...]
will behave exactly the same as:
java -agentlib:hprof=[help]|[<option>=<value>, ...]

Warnings
--------
- This is demonstration code for the JVMTI interface and use of BCI,
it is not an official product or formal part of the JDK.
- The -Xrunhprof interface will be removed in a future release.
- The option format=b is considered experimental, this format may change
in a future release.
87 |
88 |

By default, heap profiling information (sites and dump) is written 89 | out 90 | to java.hprof.txt (ascii).  91 | The monitor=y|n option has proven to be problematic and may be replaced 92 | with something more useful.
93 |

94 |

The output in most cases will contain ID's for traces, threads, 95 | objects, etc.  Each type of ID will typically start with a 96 | different number than the other ID's, e.g. traces might start with 97 | 300000.
98 |

99 |

Note: The gc_okay option 101 | is no longer supported.
102 |

103 |

Heap Allocation 104 | Profiles (heap=sites)
105 |

106 | Following is the heap allocation profile generated by running the Java 107 | compiler 108 | (javac) on a set of input files. Only parts of the 109 | profiler output are shown here. 110 |

111 |
Command used: javac -J-agentlib:hprof=heap=sites Hello.java

SITES BEGIN (ordered by live bytes) Fri Feb 6 13:13:42 2004
percent live alloc'ed stack class
rank self accum bytes objs bytes objs trace name
1 44.13% 44.13% 1117360 13967 1117360 13967 301926 java.util.zip.ZipEntry
2 8.83% 52.95% 223472 13967 223472 13967 301927 com.sun.tools.javac.util.List
3 5.18% 58.13% 131088 1 131088 1 300996 byte[]
4 5.18% 63.31% 131088 1 131088 1 300995 com.sun.tools.javac.util.Name[]

112 | A crucial piece of information in heap profile is the amount of 113 | allocation that occurs 114 | in various parts of the program. The SITES record above 115 | tells us that 44.13% of the total space was allocated for 116 | java.util.zip.ZipEntry objects. Note that the amount of live data is 117 | only a fraction 118 | of the total allocation that has occurred at a given site; the rest has 119 | been garbage collected. 120 |

A good way to relate allocation sites to the source code is to 121 | record 122 | the dynamic stack traces that led to the heap allocation. Following is 123 | another part of the profiler output that illustrates the stack traces 124 | referred to by the four allocation sites in output shown above. 125 |
126 |

127 |
TRACE 301926:
java.util.zip.ZipEntry.<init>(ZipEntry.java:101)
java.util.zip.ZipFile+3.nextElement(ZipFile.java:417)
com.sun.tools.javac.jvm.ClassReader.openArchive(ClassReader.java:1374)
com.sun.tools.javac.jvm.ClassReader.list(ClassReader.java:1631)

TRACE 301927:
com.sun.tools.javac.util.List.<init>(List.java:42)
com.sun.tools.javac.util.List.<init>(List.java:50)
com.sun.tools.javac.util.ListBuffer.append(ListBuffer.java:94)
com.sun.tools.javac.jvm.ClassReader.openArchive(ClassReader.java:1374)

TRACE 300996:
com.sun.tools.javac.util.Name$Table.<init>(Name.java:379)
com.sun.tools.javac.util.Name$Table.<init>(Name.java:481)
com.sun.tools.javac.util.Name$Table.make(Name.java:332)
com.sun.tools.javac.util.Name$Table.instance(Name.java:349)

TRACE 300995:
com.sun.tools.javac.util.Name$Table.<init>(Name.java:378)
com.sun.tools.javac.util.Name$Table.<init>(Name.java:481)
com.sun.tools.javac.util.Name$Table.make(Name.java:332)
com.sun.tools.javac.util.Name$Table.instance(Name.java:349)
128 |
129 |

130 | Each frame in the stack trace contains class name, method name, source 131 | file name, and the line number. The user can set the maximum number 132 | of frames collected by the HPROF agent. The default limit is 4. Stack 133 | traces reveal not only which methods performed heap allocation, but 134 | also which methods were ultimately responsible for making calls that 135 | resulted in memory allocation.
136 |

137 |

Heap Dump (heap=dump)

138 | A complete dump of the current live objects in the heap can be obtained 139 | with:
140 |
Command used: javac -J-agentlib:hprof=heap=dump Hello.java
141 | This is a very large output file, but can be viewed and searched in any 142 | editor.
143 |
144 |

CPU Usage Sampling 145 | Profiles (cpu=samples)
146 |

147 | HPROF can collect CPU usage information by sampling threads. Following 148 | is part of the output collected from a run 149 | of the javac compiler. 150 |

151 |
Command used: javac -J-agentlib:hprof=cpu=samples Hello.java

CPU SAMPLES BEGIN (total = 462) Fri Feb 6 13:33:07 2004
rank self accum count trace method
1 49.57% 49.57% 229 300187 java.util.zip.ZipFile.getNextEntry
2 6.93% 56.49% 32 300190 java.util.zip.ZipEntry.initFields
3 4.76% 61.26% 22 300122 java.lang.ClassLoader.defineClass2
4 2.81% 64.07% 13 300188 java.util.zip.ZipFile.freeEntry
5 1.95% 66.02% 9 300129 java.util.Vector.addElement
6 1.73% 67.75% 8 300124 java.util.zip.ZipFile.getEntry
7 1.52% 69.26% 7 300125 java.lang.ClassLoader.findBootstrapClass
8 0.87% 70.13% 4 300172 com.sun.tools.javac.main.JavaCompiler.<init>
9 0.65% 70.78% 3 300030 java.util.zip.ZipFile.open
10 0.65% 71.43% 3 300175 com.sun.tools.javac.main.JavaCompiler.<init>
152 | ... 153 | CPU SAMPLES END 154 |
155 |
156 |
157 |

158 | The HPROF agent periodically samples the stack of all running threads 159 | to record the most frequently active stack traces. The count 160 | field above indicates how many times a particular stack trace was found 161 | to be active. These stack traces correspond to the CPU usage hot spots 162 | in the application.
163 |

164 |

CPU Usage Times 165 | Profile (cpu=times)
166 |

167 | HPROF can collect CPU usage information by injecting code into every 168 | method entry and exit, keeping track of exact method call counts and 169 | the time spent in each method. This uses Byte Code Injection (BCI) and 170 | runs considerably slower than cpu=samples. Following is part of the 171 | output collected from a run 172 | of the javac compiler. 173 |

174 |
Command used: javac -J-agentlib:hprof=cpu=times Hello.java

CPU TIME (ms) BEGIN (total = 2082665289) Fri Feb 6 13:43:42 2004
rank self accum count trace method
1 3.70% 3.70% 1 311243 com.sun.tools.javac.Main.compile
2 3.64% 7.34% 1 311242 com.sun.tools.javac.main.Main.compile
3 3.64% 10.97% 1 311241 com.sun.tools.javac.main.Main.compile
4 3.11% 14.08% 1 311173 com.sun.tools.javac.main.JavaCompiler.compile
5 2.54% 16.62% 8 306183 com.sun.tools.javac.jvm.ClassReader.listAll
6 2.53% 19.15% 36 306182 com.sun.tools.javac.jvm.ClassReader.list
7 2.03% 21.18% 1 307195 com.sun.tools.javac.comp.Enter.main
8 2.03% 23.21% 1 307194 com.sun.tools.javac.comp.Enter.complete
9 1.68% 24.90% 1 306392 com.sun.tools.javac.comp.Enter.classEnter
10 1.68% 26.58% 1 306388 com.sun.tools.javac.comp.Enter.classEnter

...
CPU TIME (ms) END
175 | Here the count represents the true count of the times this method was 176 | entered, and the percentages represent a measure of thread CPU time 177 | spent in those methods.
178 |
179 |

Binary Dump Format 180 | (format=b)

181 | The basic fields in the binary output are u1 (1 byte), u2 (2 byte), u4 182 | (4 byte), and u8 (8 byte). An ID in this implementation is a u4, 183 | however the size of an ID is really determined by the "size of 184 | identifiers" field in the header.
185 |
186 | WARNING: This format is still 187 | considered highly experimental, however, all attempts were made to 188 | match the format of past HPROF implementations.
189 |
190 | The binary output begins with the information:
191 |
192 | 194 | 195 | 196 | 198 | 203 | 204 | 205 | 207 | 211 | 212 | 213 | 215 | 217 | 218 | 219 | 221 | 223 | 224 | 225 |
[u1]*
197 |
An initial NULL terminated 199 | series of bytes representing the format name and version, in this 200 | implementation and historically, the string "JAVA PROFILE 1.0.1" (18 201 | u1 bytes) followed by a NULL byte. If the TAG "HEAP DUMP SEGMENT" is 202 | used this string will be "JAVA PROFILE 1.0.2".
u4
206 |
size of identifiers. Identifiers 208 | are used to represent UTF8 strings, objects, stack traces, etc. They 209 | can have the same size as host pointers or sizeof(void*), but are not 210 | required to be.
u4
214 |
high word of number of 216 | milliseconds since 0:00 GMT, 1/1/70
u4
220 |
low word of number of 222 | milliseconds since 0:00 GMT, 1/1/70
226 |
227 | Followed by a sequence of 228 | records that look like:
229 |
230 | 232 | 233 | 234 | 236 | 238 | 239 | 240 | 242 | 246 | 247 | 248 | 250 | 254 | 255 | 256 | 258 | 262 | 263 | 264 |
u1
235 |
TAG: denoting the type of the 237 | record
u4
241 |
TIME: number of microseconds 243 | since the 244 | time stamp in the header
245 |
u4
249 |
LENGTH: number of bytes that 251 | follow this 252 | u4 field and belong to this record
253 |
[u1]*
257 |
BODY: as many bytes as specified 259 | in 260 | the above u4 field
261 |
265 |
266 |
267 | The following TAGs are supported:
268 |
269 | 271 | 272 | 273 | 275 | 277 | 298 | 299 | 300 | 302 | 304 | 337 | 338 | 339 | 341 | 343 | 357 | 358 | 359 | 361 | 363 | 446 | 447 | 448 | 450 | 452 | 484 | 485 | 486 | 488 | 490 | 624 | 625 | 626 | 628 | 630 | 662 | 663 | 664 | 666 | 668 | 712 | 713 | 714 | 716 | 718 | 732 | 733 | 734 | 738 | 742 | 1296 | 1297 | 1298 | 1300 | 1302 | 1305 | 1306 | 1307 | 1309 | 1311 | 1351 | 1352 | 1353 | 1355 | 1357 | 1395 | 1396 | 1397 |
STRING IN UTF8
274 |
0x01
276 |
278 | 280 | 281 | 282 | 284 | 286 | 287 | 288 | 290 | 293 | 294 | 295 |
ID
283 |
ID for this string
285 |
[u1]*
289 |
UTF8 characters for string 291 | (NOT NULL terminated)
292 |
296 |
297 |
LOAD CLASS
301 |
0x02
303 |
305 | 307 | 308 | 309 | 311 | 314 | 315 | 316 | 318 | 320 | 321 | 322 | 324 | 326 | 327 | 328 | 330 | 332 | 333 | 334 |
u4
310 |
class serial number 312 | (always > 0)
313 |
ID
317 |
class object ID
319 |
u4
323 |
stack trace serial number
325 |
ID
329 |
class name string ID
331 |
335 |
336 |
UNLOAD CLASS
340 |
0x03
342 |
344 | 346 | 347 | 348 | 350 | 352 | 353 | 354 |
u4
349 |
class serial number
351 |
355 |
356 |
STACK FRAME
360 |
0x04
362 |
364 | 366 | 367 | 368 | 370 | 372 | 373 | 374 | 376 | 378 | 379 | 380 | 382 | 384 | 385 | 386 | 388 | 390 | 391 | 392 | 394 | 396 | 397 | 398 | 400 | 441 | 442 | 443 |
ID
369 |
stack frame ID
371 |
ID
375 |
method name string ID
377 |
ID
381 |
method signature string ID
383 |
ID
387 |
source file name string ID
389 |
u4
393 |
class serial number
395 |
u4
399 |
401 | 403 | 404 | 405 | 407 | 409 | 410 | 411 | 413 | 416 | 417 | 418 | 420 | 422 | 423 | 424 | 426 | 429 | 430 | 431 | 433 | 436 | 437 | 438 |
> 0
406 |
line number
408 |
0
412 |
no line information 414 | available
415 |
-1
419 |
unknown location
421 |
-2
425 |
compiled method (Not implemented)
428 |
-3
432 |
native method (Not implemented)
435 |
439 |
440 |
444 |
445 |
STACK TRACE
449 |
0x05
451 |
453 | 455 | 456 | 457 | 459 | 461 | 462 | 463 | 465 | 467 | 468 | 469 | 471 | 473 | 474 | 475 | 477 | 479 | 480 | 481 |
u4
458 |
stack trace serial number
460 |
u4
464 |
thread serial number
466 |
u4
470 |
number of frames
472 |
[ID]*
476 |
series of stack frame ID's
478 |
482 |
483 |
ALLOC SITES
487 |
0x06
489 |
491 | 493 | 494 | 495 | 497 | 527 | 528 | 529 | 531 | 534 | 535 | 536 | 538 | 540 | 541 | 542 | 544 | 546 | 547 | 548 | 550 | 552 | 553 | 554 | 556 | 558 | 559 | 560 | 562 | 619 | 620 | 621 |
u2
496 |
Bit mask flags:
498 | 500 | 501 | 502 | 504 | 507 | 508 | 509 | 511 | 514 | 515 | 516 | 518 | 522 | 523 | 524 |
0x1
503 |
incremental vs. 505 | complete
506 |
0x2
510 |
sorted 512 | by allocation vs. line
513 |
0x4
517 |
whether to force GC 519 | (Not 520 | Implemented)
521 |
525 |
526 |
u4
530 |
cutoff ratio (floating 532 | point)
533 |
u4
537 |
total live bytes
539 |
u4
543 |
total live instances
545 |
u8
549 |
total bytes allocated
551 |
u8
555 |
total instances allocated
557 |
u4
561 |
number of sites that 563 | follow:
564 | 566 | 567 | 568 | 570 | 574 | 575 | 576 | 578 | 580 | 581 | 582 | 584 | 587 | 588 | 589 | 591 | 593 | 594 | 595 | 597 | 600 | 601 | 602 | 604 | 607 | 608 | 609 | 611 | 614 | 615 | 616 |
u1
569 |
array indicator: 0 571 | means not an array, non-zero means an array of this type (See Basic Type)
573 |
u4
577 |
class serial number
579 |
u4
583 |
stack trace serial 585 | number
586 |
u4
590 |
number of live bytes
592 |
u4
596 |
number of live 598 | instances
599 |
u4
603 |
number of bytes 605 | allocated
606 |
u4
610 |
number of instances 612 | allocated
613 |
617 |
618 |
622 |
623 |
HEAP SUMMARY
627 |
0x07
629 |
631 | 633 | 634 | 635 | 637 | 639 | 640 | 641 | 643 | 645 | 646 | 647 | 649 | 651 | 652 | 653 | 655 | 657 | 658 | 659 |
u4
636 |
total live bytes
638 |
u4
642 |
total live instances
644 |
u8
648 |
total bytes allocated
650 |
u8
654 |
total instances allocated
656 |
660 |
661 |
START THREAD
665 |
0x0A
667 |
669 | 671 | 672 | 673 | 675 | 677 | 678 | 679 | 681 | 683 | 684 | 685 | 687 | 689 | 690 | 691 | 693 | 695 | 696 | 697 | 699 | 701 | 702 | 703 | 705 | 707 | 708 | 709 |
u4
674 |
thread serial number
676 |
ID
680 |
thread object ID
682 |
u4
686 |
stack trace serial number
688 |
ID
692 |
thread name string ID
694 |
ID
698 |
thread group name ID
700 |
ID
704 |
thread parent group name ID
706 |
710 |
711 |
END THREAD
715 |
0x0B
717 |
719 | 721 | 722 | 723 | 725 | 727 | 728 | 729 |
u4
724 |
thread serial number
726 |
730 |
731 |
HEAP DUMP
735 | or
736 | HEAP DUMP SEGMENT
737 |
0x0C
739 | or
740 | 0x1C
741 |
Contains any number of sub-tags, 743 | each begins a u1 field (no order implied here):
744 | 746 | 747 | 748 | 750 | 752 | 766 | 767 | 768 | 770 | 772 | 792 | 793 | 794 | 796 | 798 | 825 | 826 | 827 | 829 | 831 | 857 | 858 | 859 | 861 | 863 | 883 | 884 | 885 | 887 | 889 | 903 | 904 | 905 | 907 | 909 | 929 | 930 | 931 | 933 | 935 | 949 | 950 | 951 | 953 | 955 | 982 | 983 | 984 | 986 | 988 | 1151 | 1152 | 1153 | 1155 | 1157 | 1199 | 1200 | 1201 | 1203 | 1205 | 1245 | 1246 | 1247 | 1249 | 1251 | 1291 | 1292 | 1293 |
ROOT UNKNOWN
749 |
0xFF
751 |
753 | 755 | 756 | 757 | 759 | 761 | 762 | 763 |
ID
758 |
object ID
760 |
764 |
765 |
ROOT JNI GLOBAL
769 |
0x01
771 |
773 | 775 | 776 | 777 | 779 | 781 | 782 | 783 | 785 | 787 | 788 | 789 |
ID
778 |
object ID
780 |
ID
784 |
JNI global ref ID
786 |
790 |
791 |
ROOT JNI LOCAL
795 |
0x02
797 |
799 | 801 | 802 | 803 | 805 | 807 | 808 | 809 | 811 | 813 | 814 | 815 | 817 | 820 | 821 | 822 |
ID
804 |
object ID
806 |
u4
810 |
thread serial number
812 |
u4
816 |
frame number in 818 | stack trace (-1 for empty)
819 |
823 |
824 |
ROOT JAVA FRAME
828 |
0x03
830 |
832 | 834 | 835 | 836 | 838 | 840 | 841 | 842 | 844 | 846 | 847 | 848 | 850 | 852 | 853 | 854 |
ID
837 |
object ID
839 |
u4
843 |
thread serial number
845 |
u4
849 |
frame number in 851 | stack trace (-1 for empty)
855 |
856 |
ROOT NATIVE STACK
860 |
0x04
862 |
864 | 866 | 867 | 868 | 870 | 872 | 873 | 874 | 876 | 878 | 879 | 880 |
ID
869 |
object ID
871 |
u4
875 |
thread serial number
877 |
881 |
882 |
ROOT STICKY CLASS
886 |
0x05
888 |
890 | 892 | 893 | 894 | 896 | 898 | 899 | 900 |
ID
895 |
object ID
897 |
901 |
902 |
ROOT THREAD BLOCK
906 |
0x06
908 |
910 | 912 | 913 | 914 | 916 | 918 | 919 | 920 | 922 | 924 | 925 | 926 |
ID
915 |
object ID
917 |
u4
921 |
thread serial number
923 |
927 |
928 |
ROOT MONITOR USED
932 |
0x07
934 |
936 | 938 | 939 | 940 | 942 | 944 | 945 | 946 |
ID
941 |
object ID
943 |
947 |
948 |
ROOT THREAD OBJECT
952 |
0x08
954 |
956 | 958 | 959 | 960 | 962 | 964 | 965 | 966 | 968 | 970 | 971 | 972 | 974 | 977 | 978 | 979 |
ID
961 |
thread object ID
963 |
u4
967 |
thread serial number
969 |
u4
973 |
stack trace serial 975 | number
976 |
980 |
981 |
CLASS DUMP
985 |
0x20
987 |
989 | 991 | 992 | 993 | 995 | 997 | 998 | 999 | 1001 | 1004 | 1005 | 1006 | 1008 | 1010 | 1011 | 1012 | 1014 | 1017 | 1018 | 1019 | 1021 | 1023 | 1024 | 1025 | 1027 | 1030 | 1031 | 1032 | 1034 | 1036 | 1037 | 1038 | 1040 | 1042 | 1043 | 1044 | 1046 | 1049 | 1050 | 1051 | 1053 | 1084 | 1085 | 1086 | 1088 | 1119 | 1120 | 1121 | 1123 | 1146 | 1147 | 1148 |
ID
994 |
class object ID
996 |
u4
1000 |
stack trace serial 1002 | number
1003 |
ID
1007 |
super class object ID
1009 |
ID
1013 |
class loader object 1015 | ID
1016 |
ID
1020 |
signers object ID
1022 |
ID
1026 |
protection domain 1028 | object ID
1029 |
ID
1033 |
reserved
1035 |
ID
1039 |
reserved
1041 |
u4
1045 |
instance size (in 1047 | bytes)
1048 |
u2
1052 |
size of constant 1054 | pool and number of records that follow:
1055 | 1057 | 1058 | 1059 | 1061 | 1064 | 1065 | 1066 | 1068 | 1071 | 1072 | 1073 | 1075 | 1079 | 1080 | 1081 |
u2
1060 |
constant pool 1062 | index
1063 |
u1
1067 |
type of entry: 1069 | (See Basic Type)
1070 |
value
1074 |
value of entry 1076 | (u1, u2, u4, or u8 based on type of entry)
1078 |
1082 |
1083 |
u2
1087 |
Number of static 1089 | fields:
1090 | 1092 | 1093 | 1094 | 1096 | 1099 | 1100 | 1101 | 1103 | 1106 | 1107 | 1108 | 1110 | 1114 | 1115 | 1116 |
ID
1095 |
static field 1097 | name string ID
1098 |
u1
1102 |
type of field: 1104 | (See Basic Type)
1105 |
value
1109 |
value of entry 1111 | (u1, u2, u4, or u8 based on type of field)
1113 |
1117 |
1118 |
u2
1122 |
Number of instance 1124 | fields (not including super class's)
1125 | 1127 | 1128 | 1129 | 1131 | 1134 | 1135 | 1136 | 1138 | 1141 | 1142 | 1143 |
ID
1130 |
field name 1132 | string ID
1133 |
u1
1137 |
type of field: 1139 | (See Basic Type)
1140 |
1144 |
1145 |
1149 |
1150 |
INSTANCE DUMP
1154 |
0x21
1156 |

1158 | 1160 | 1161 | 1162 | 1164 | 1166 | 1167 | 1168 | 1170 | 1173 | 1174 | 1175 | 1177 | 1179 | 1180 | 1181 | 1183 | 1186 | 1187 | 1188 | 1190 | 1194 | 1195 | 1196 |
ID
1163 |
object ID
1165 |
u4
1169 |
stack trace serial 1171 | number
1172 |
ID
1176 |
class object ID
1178 |
u4
1182 |
number of bytes that 1184 | follow
1185 |
[value]*
1189 |
instance field 1191 | values (this class, followed by super class, etc)
1193 |
1197 |
1198 |
OBJECT ARRAY DUMP
1202 |
0x22
1204 |

1206 | 1208 | 1209 | 1210 | 1212 | 1214 | 1215 | 1216 | 1218 | 1221 | 1222 | 1223 | 1225 | 1227 | 1228 | 1229 | 1231 | 1234 | 1235 | 1236 | 1238 | 1240 | 1241 | 1242 |
ID
1211 |
array object ID
1213 |
u4
1217 |
stack trace serial 1219 | number
1220 |
u4
1224 |
number of elements
1226 |
ID
1230 |
array class object 1232 | ID
1233 |
[ID]*
1237 |
elements
1239 |
1243 |
1244 |
PRIMITIVE ARRAY DUMP
1248 |
0x23
1250 |
1252 | 1254 | 1255 | 1256 | 1258 | 1260 | 1261 | 1262 | 1264 | 1267 | 1268 | 1269 | 1271 | 1273 | 1274 | 1275 | 1277 | 1280 | 1281 | 1282 | 1284 | 1286 | 1287 | 1288 |
ID
1257 |
array object ID
1259 |
u4
1263 |
stack trace serial 1265 | number
1266 |
u4
1270 |
number of elements
1272 |
u1
1276 |
element type (See Basic Type)
1279 |
[u1]*
1283 |
elements (packed 1285 | array)
1289 |
1290 |
1294 |
1295 |
HEAP DUMP END
1299 |
0x2C
1301 |
Terminates a series of HEAP DUMP 1303 | SEGMENTS.  Concatenation of HEAP DUMP SEGMENTS equals a HEAP DUMP.
1304 |
CPU SAMPLES
1308 |
0x0D
1310 |
1312 | 1314 | 1315 | 1316 | 1318 | 1320 | 1321 | 1322 | 1324 | 1346 | 1347 | 1348 |
u4
1317 |
total number of samples
1319 |
u4
1323 |
number of traces that 1325 | follow:
1326 | 1328 | 1329 | 1330 | 1332 | 1334 | 1335 | 1336 | 1338 | 1341 | 1342 | 1343 |
u4
1331 |
number of samples
1333 |
u4
1337 |
stack trace serial 1339 | number
1340 |
1344 |
1345 |
1349 |
1350 |
CONTROL SETTINGS
1354 |
0x0E
1356 |
1358 | 1360 | 1361 | 1362 | 1364 | 1384 | 1385 | 1386 | 1388 | 1390 | 1391 | 1392 |
u4
1363 |
Bit mask flags:
1365 | 1367 | 1368 | 1369 | 1371 | 1373 | 1374 | 1375 | 1377 | 1379 | 1380 | 1381 |
0x1
1370 |
alloc traces on/off
1372 |
0x2
1376 |
cpu sampling on/off
1378 |
1382 |
1383 |
u2
1387 |
stack trace depth
1389 |
1393 |
1394 |
1398 |
1399 |
Basic Type 1400 | 1402 | 1403 | 1404 | 1406 | 1408 | 1409 | 1410 | 1412 | 1414 | 1415 | 1416 | 1418 | 1420 | 1421 | 1422 | 1424 | 1426 | 1427 | 1428 | 1430 | 1432 | 1433 | 1434 | 1436 | 1438 | 1439 | 1440 | 1442 | 1444 | 1445 | 1446 | 1448 | 1450 | 1451 | 1452 | 1454 | 1456 | 1457 | 1458 |
2
1405 |
object
1407 |
4
1411 |
boolean
1413 |
5
1417 |
char
1419 |
6
1423 |
float
1425 |
7
1429 |
double
1431 |
8
1435 |
byte
1437 |
9
1441 |
short
1443 |
10
1447 |
int
1449 |
11
1453 |
long
1455 |
1459 |

Handling of Arrays

1460 |
1461 | There will be a "LOAD CLASS" tag for type type of each array 1462 | in the dump. In the LOAD CLASS record, the class name string ID 1463 | will refer to a string with a human-readable name of the array 1464 | type that is formatted as the type name would be in Java source 1465 | code. Thus, the LOAD CLASS record for the type char[] will 1466 | be "char[]", for short[][][] will be "short[][][]" and for 1467 | MyType[] will be "MyType[]". 1468 |
1469 |

Socket Connection and 1470 | Communication

1471 |
1472 | WARNING: This command format is 1473 | still 1474 | considered highly experimental, however, all attempts were made to 1475 | match the format of past HPROF implementations.
1476 |
1477 |
1478 | Commands can be sent to HPROF via the socket connection, the accepted 1479 | COMMAND TAGS are:
1480 |
1481 | 1483 | 1484 | 1485 | 1488 | 1490 | 1491 | 1492 | 1494 | 1496 | 1497 | 1498 | 1500 | 1502 | 1503 | 1504 | 1506 | 1508 | 1509 | 1510 | 1512 | 1514 | 1515 | 1516 | 1518 | 1520 | 1521 | 1522 | 1524 | 1526 | 1527 | 1528 | 1530 | 1532 | 1533 | 1534 | 1537 | 1539 | 1540 | 1541 |
FORCE GC (Not implemented)
1487 |
0x01
1489 |
DUMP HEAP
1493 |
0x02
1495 |
ALLOC SITES
1499 |
0x03
1501 |
HEAP SUMMARY
1505 |
0x04
1507 |
EXIT THE VM
1511 |
0x05
1513 |
DUMP TRACES
1517 |
0x06
1519 |
CPU SAMPLES
1523 |
0x07
1525 |
CONTROL
1529 |
0x08
1531 |
EOF (used to terminate socket 1535 | connection)
1536 |
0xFF
1538 |
1542 |
1543 | The commands take the form:
1544 |
1545 | 1547 | 1548 | 1549 | 1551 | 1553 | 1554 | 1555 | 1557 | 1559 | 1560 | 1561 | 1563 | 1565 | 1566 | 1567 | 1569 | 1730 | 1731 | 1732 |
u1
1550 |
COMMAND TAG
1552 |
u4
1556 |
serial number
1558 |
u4
1562 |
number of bytes that follow
1564 |
[u1]*
1568 |
1570 | 1572 | 1573 | 1574 | 1576 | 1597 | 1598 | 1599 | 1601 | 1622 | 1623 | 1624 | 1626 | 1726 | 1727 | 1728 |
ALLOC SITES
1575 |
1577 | 1579 | 1580 | 1581 | 1583 | 1585 | 1586 | 1587 | 1589 | 1592 | 1593 | 1594 |
u2
1582 |
Flags:
1584 |
u4
1588 |
cutoff ratio 1590 | (floating point between 0.0 and 1.0)
1591 |
1595 |
1596 |
CPU SAMPLES
1600 |
1602 | 1604 | 1605 | 1606 | 1608 | 1610 | 1611 | 1612 | 1614 | 1617 | 1618 | 1619 |
u2
1607 |
ignored
1609 |
u4
1613 |
cutoff ratio 1615 | (floating point between 0.0 and 1.0)
1616 |
1620 |
1621 |
CONTROL
1625 |
1627 | 1629 | 1630 | 1631 | 1633 | 1721 | 1722 | 1723 |
u2
1632 |
Sub option:
1634 | 1636 | 1637 | 1638 | 1640 | 1643 | 1644 | 1645 | 1647 | 1650 | 1651 | 1652 | 1654 | 1670 | 1671 | 1672 | 1674 | 1689 | 1690 | 1691 | 1693 | 1696 | 1697 | 1698 | 1700 | 1716 | 1717 | 1718 |
0x1
1639 |
Turn alloc 1641 | traces on
1642 |
0x2
1646 |
Turn alloc 1648 | traces off
1649 |
0x3
1653 |
Turn CPU 1655 | sampling on:
1656 | 1658 | 1659 | 1660 | 1662 | 1665 | 1666 | 1667 |
ID
1661 |
thread 1663 | object ID (0 for all threads)
1664 |
1668 |
1669 |
0x4
1673 |
Turn CPU 1675 | sampling off:
1676 | 1678 | 1679 | 1680 | 1682 | 1684 | 1685 | 1686 |
ID
1681 |
thread 1683 | object ID (0 for all threads)
1687 |
1688 |
0x5
1692 |
Clear CPU 1694 | sampling
1695 |
0x6
1699 |
Set max stack 1701 | depth:
1702 | 1704 | 1705 | 1706 | 1708 | 1711 | 1712 | 1713 |
u2
1707 |
New max 1709 | stack depth
1710 |
1714 |
1715 |
1719 |
1720 |
1724 |
1725 |
1729 |
1733 |
1734 |

1735 |

Source Code
1736 |

1737 | The source to HPROF is available in the JDK download in the 1738 | demo/jvmti/hprof directory. 1739 |

*As used on this web site, the terms "Java 1740 | Virtual Machine" or "JVM" mean a virtual machine for the Java platform. 1741 |

1742 |

1743 |
1744 | Last modified: %G% 1745 | 1746 | 1747 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndroidAdvanceWithGeektime/Chapter04/840fb9cda4102bdd5bb5c651ba580427821edceb/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 29 18:03:28 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':DuplicatedBitmapAnalyzer' 2 | -------------------------------------------------------------------------------- /tools/DuplicatedBitmapAnalyzer-1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndroidAdvanceWithGeektime/Chapter04/840fb9cda4102bdd5bb5c651ba580427821edceb/tools/DuplicatedBitmapAnalyzer-1.0.jar --------------------------------------------------------------------------------