Heap map
519: zygote64 Address Kbytes PSS Dirty Swap Mode Mapping // capacity_:536870912 = 524288k = 2048 + 522204 0000000012c00000 2084 564 556 0 rw--- dalvik-main space (deleted) 0000000012e09000 522204 0 0 0 ----- dalvik-main space (deleted) 0000000032c00000 4 0 0 0 rw--- dalvik-main space 1 (deleted) 0000000032c01000 524284 0 0 0 ----- dalvik-main space 1 (deleted) 0000000070c86000 15204 797 248 0 rw--- system@framework@boot.art // image space 指定地址为0x70c86000 0000000071b5f000 38044 4136 0 0 r---- boot.oat 0000000074086000 41072 1456 0 0 r-x-- boot.oat 00000000768a2000 4 4 0 0 rw--- boot.oat // non_moving_space_capacity:67108864 = 65536kb = 1756 + 4 + 55588 + 8188 00000000768a3000 1756 144 88 0 rw--- dalvik-zygote space (deleted) 0000000076a5a000 4 4 4 0 rw--- dalvik-non moving space (deleted) 0000000076a5b000 55588 0 0 0 ----- dalvik-non moving space (deleted) 000000007a0a4000 8188 0 0 0 rw--- dalvik-non moving space (deleted) 000000007a8a3000 524288 459 0 0 rw--- dalvik-free list large object space (deleted) 000000555b3b5000 20 0 0 0 r-x-- app_process64 000000555b3c9000 4 0 0 0 r---- app_process64 000000555b3ca000 4 0 0 0 rw--- app_process64 000000557fe77000 29308 1409 464 0 rw--- [heap] 0000007f9eebd000 8192 0 0 0 rw--- dalvik-allocspace main rosalloc space mark-bitmap 3 (deleted) 0000007f9f6bd000 8192 0 0 0 rw--- dalvik-allocspace main rosalloc space live-bitmap 3 (deleted) ................. 0000007fa48be000 176 15 0 0 r---- system@framework@boot.art// image space mapped bitmap 地址由操作系统分配 01-01 20:19:43.085 519 519 E art : HTC++++ image_filename: /data/dalvik-cache/arm64/system@framework@boot.art 01-01 20:19:43.085 519 519 E art : HTC++++sizeof(image_header) = 140 01-01 20:19:43.085 519 519 E art : HTC+++Image file for image heap: 15749120 vs 15566800 01-01 20:19:43.085 519 519 E art : HTC++++xxxxxend_of_bitmap: 15749120 01-01 20:19:43.085 519 519 E art : HTC++++xxxxxend_of_bitmap: 15749120 01-01 20:19:43.085 519 519 E art : HTC++++mmap(0x70c86000, 15568896, 0x3, 0x2, 6, 0) of file '/data/dalvik-cache/arm64/system@framework@boot.art' See process maps in the log. 01-01 20:19:43.085 519 519 E art : HTC++++ bitmap size:180224bitmap offset:15568896 01-01 20:19:43.085 519 519 E art : HTC++++mmap(0x0, 180224, 0x1, 0x2, 6, 15568896) of file '/data/dalvik-cache/arm64/system@framework@boot.art' See process maps in the log. 01-01 20:19:43.085 519 519 E art : HTC++++imagespace /data/dalvik-cache/arm64/system@framework@boot.art live-bitmap 0 sizeof(image_header) = 140 --------------------------------------------------------------------------------------- -rw-r--r-- root root 15749120 2016-03-24 10:50 system@framework@boot.art lrwxrwxrwx root root 2016-03-24 10:50 system@framework@boot.oat -> /system/framework/arm64/boot.oat system@framework@boot.art 15749120 //实际image file映射大小为 image_header.GetImageSize() =15566800 mmap(0x70c86000, 15568896, 0x3, 0x2, 6, 0) 映射的地址: 0x70c86000 映射到内存中的起始地址 image_header.GetImageBegin() 映射的字节数: 15568896 = 15204k 这个是image_header.GetImageSize()=15566800 = 0xed87d0 = 15201.95k页对齐后的数据 --------------------------------------------------------------------------------------- mmap(0x0, 180224, 0x1, 0x2, 6, 15568896) 在内存中映射地址为null,即为操作系统分配 bitmap size: 180224 = 0x2c000 = 176K bitmap offset: 文件中的偏移位置为 15568896,显然在文件中是紧紧挨着image的 15749120 = 15568896 + 180224 显然刚好boot.art = image + bitmap,只不过他们在内存中映射的地址不相邻 --------------------------------------------------------------------------------------- 0000000070c86000 15204 779 248 0 rw--- system@framework@boot.art 0000000071b5f000 38044 4186 0 0 r---- boot.oat 70c8 6000 => 0060 c870 ed 87d0 => d087 ed00 0030 8a76 => 0x768a3000 zygote space map address 0000000: 6172 740a 3031 3700 0060 c870 d087 ed00 art.017..`.p.... 0000010: efa4 7d4d 00f0 b571 0000 b671 0c10 8a76 ..}M...q...q...v 0000020: 0030 8a76 0060 c800 5800 4571 0800 0000 .0.v.`..X.Eq.... 0000030: 0100 0000 0000 0000 0821 ae00 0821 ae00 .........!...!.. 0000040: 5087 0800 58a8 b600 e825 3000 40ce e600 P...X....%0.@... 0000050: 90b9 0600 0090 ed00 00c0 0200 f02c af71 .............,.q 0000060: 0000 0000 282d af71 0000 0000 602d af71 ....(-.q....`-.q 0000070: 0000 0000 982d af71 0000 0000 d02d af71 .....-.q.....-.q 0000080: 0000 0000 082e af71 0000 0000 0000 0000 .......q........ 0000090: 60f2 4971 0000 0000 510d 0000 48f5 4971 `.Iq....Q...H.Iq 00000a0: d0f5 4971 58f6 4971 e0f6 4971 68f7 4971 ..IqX.Iq..Iqh.Iq 00000b0: 40f0 4971 0000 0000 082e 6d71 f0f7 4971 @.Iq......mq..Iq
03-27 18:02:41.416 519 519 E art : HTC++++/data/dalvik-cache/arm64/system@framework@boot.art SpaceType:0 GcRetentionPolicy:0 03-27 18:02:41.417 519 519 E art : HTC++++zygote / non moving space SpaceType:1 GcRetentionPolicy:1 03-27 18:02:41.418 519 519 E art : HTC++++main rosalloc space SpaceType:1 GcRetentionPolicy:1 03-27 18:02:41.418 519 519 E art : HTC++++main rosalloc space 1 SpaceType:1 GcRetentionPolicy:1 03-27 18:02:41.419 519 519 E art : HTC++++free list large object space SpaceType:4 GcRetentionPolicy:1 03-27 18:02:45.768 519 519 E art : HTC++++main rosalloc space SpaceType:1 GcRetentionPolicy:1 03-27 18:02:45.768 519 519 E art : HTC++++Zygote space SpaceType:2 GcRetentionPolicy:2 03-27 18:02:45.768 519 519 E art : HTC++++non moving space SpaceType:1 GcRetentionPolicy:1 03-27 18:02:42.642 520 520 E art : HTC++++/data/dalvik-cache/arm/system@framework@boot.art SpaceType:0 GcRetentionPolicy:0 03-27 18:02:42.643 520 520 E art : HTC++++zygote / non moving space SpaceType:1 GcRetentionPolicy:1 03-27 18:02:42.643 520 520 E art : HTC++++main rosalloc space SpaceType:1 GcRetentionPolicy:1 03-27 18:02:42.644 520 520 E art : HTC++++main rosalloc space 1 SpaceType:1 GcRetentionPolicy:1 03-27 18:02:42.644 520 520 E art : HTC++++mem map large object space SpaceType:4 GcRetentionPolicy:1 03-27 18:02:56.060 520 520 E art : HTC++++main rosalloc space SpaceType:1 GcRetentionPolicy:1 03-27 18:02:56.060 520 520 E art : HTC++++Zygote space SpaceType:2 GcRetentionPolicy:2 03-27 18:02:56.060 520 520 E art : HTC++++non moving space SpaceType:1 GcRetentionPolicy:1
Compacting GC对Bump Pointer Space的使用是略有不同的,因此,我们又分为Semi-Space GC、Generational Semi-Space GC和Mark-Compact GC三种情况来介绍Bump Pointer Space。
Semi-Space GC:
它由两个Bump Pointer Space组成
Bump Pointer Space 1和Bump Pointer Space 2分别称为From Space和To Space。其中,对象的分配发生在From Space中。在Bump Pointer Space中,有一个指针end_,始终指向下一次要分配的内存块的起始地址。因此,在Bump Pointer Space上分配内存的逻辑是很简单的,只要前指针end_向前移动指定的大小即可。这也是Bump Pointer的由来。当From Space不能满足内存分配要求时,就会触发一次Semi-Space GC,结果就是From Space和To Space互换了位置,并且原来在From Space上的Live Object按地址值从小到大的顺序移动到了原来的To Space上去。
Generational Semi-Space GC:
Generational Semi-Space GC与Semi-Space GC是基本相同的,只不过前者在移动对象时,会考虑到对象的年龄。如果一个对象在多次GC中都能存活下来,那么就会将它移动到一个Promote Space中去。这是因为时间局部性原理,一个对象如果在前面几次GC中都能存活下来,那么它在下一次GC中也很有可能是存活的。因此,就把它移动到一个 Promote Space中去。由于Promote Space是一个Non-Moving Space,因此以后在这个Space上的对象不会再被移动。通过这种方式,就可以有效地减少在Generational Semi-Space GC中要移动的对象的个数,从而提高GC效率。
Obj-1是一个在多次GC中存活下来的对象,因此,在下一次Generational Semi-Space中,它就被移动到了Promote Space中,而Obj-3就像Semi-Space GC中的Live Object一样,被移动到了To Space中。
Mark-Compact GC
在执行Mark-Compact GC时,所有存活的对象都被移动到了另外一端,通过这种方式就达到压缩的效果。
Semi-Space和Generational Semi-Space需要用到两个Bump Pointer Space,这也是Semi-Space的由来,然而Mark-Compact GC只用到了一个Bump Pointer Space
Ros Alloc Space和Dl Malloc Space:
但是Ros Alloc Space不像Dl Malloc Space一样使用C库内存管理接口来分配和释放内存,而是采用一种称为Ros(Runs-of-slots)的接口来进行内存分配和释放。
Ros算法其实与Linux内核使用的SLAB算法类似,它们的核心思想都是将内存分为若干个Bucket,每一个Bucket都管理着相同大小的内存 块。这样在分配内存时,就会先根据要分配的内存大小找到最合适的Bucket,然后再从这个Bucket找到一块空闲的内存进行分配。这是一种Best Fit分配策略,好处是可以将大小相同的对象集中在一起分配,这样可以有效地减少内存碎片。
[dalvik.vm.heapgrowthlimit]: [192m] [dalvik.vm.heapmaxfree]: [8m] [dalvik.vm.heapminfree]: [2m] [dalvik.vm.heapsize]: [512m] [dalvik.vm.heapstartsize]: [8m] [dalvik.vm.heaptargetutilization]: [0.75] 01-01 00:15:37.665 524 524 E art : HTC++++ requested_alloc_space_begin:0x766bf000 01-01 00:15:37.666 524 524 E art : HTC+++++ capacity_536870912 01-01 00:15:37.666 524 524 E art : HTC+++++DlMallocSpace::CreateFromMemMap() kDefaultStartingSize:4096, initial_size:8388608, size:67108864 01-01 00:15:37.666 524 524 E art : HTC+++++Runtime::Current()->RunningOnValgrind():0 01-01 00:15:37.666 524 524 E art : HTC++++ heap_capacity:67108864, bitmap_size:1048576 01-01 00:15:37.666 524 524 E art : HTC++++ heap_capacity:67108864, bitmap_size:1048576 01-01 00:15:37.666 524 524 E art : HTC++++zygote / non moving space SpaceType:1 GcRetentionPolicy:1 01-01 00:15:37.666 524 524 E art : HTC+++++growth_limit_:201326592, initial_size:8388608 01-01 00:15:37.668 524 524 E art : HTC++++main rosalloc space SpaceType:1 GcRetentionPolicy:1 01-01 00:15:37.668 524 524 E art : HTC+++kUseRosAlloc:1 01-01 00:15:37.668 524 524 E art : HTC+++CardTable::kCardSize:128 image_header.GetImageSection(ImageHeader::kSectionObjects).End(): 11411720 HTC++++kBitsPerByte:8, kAlignment:8 01-01 16:58:53.981 538 538 E art : HTC+++::CreateFromMemMap() name:imagespace /data/dalvik-cache/arm64/system@framework@boot.art live-bitmap 0, heap_capacity:11534336 01-01 16:58:53.981 538 538 E art : HTC++++heap_begin:0x6f3ff000 //依据bitmap 算出imagespace的大小 180224 * 64 = 11534336 01-01 16:58:53.981 538 538 E art : HTC++++ heap_capacity:11534336, bitmap_size:180224 = 176K ///image space: 11534336 = 11264k=11M 01-01 16:58:53.981 538 538 E art : HTC+++++ image_header.GetImageSection(ImageHeader::kSectionObjects).End(): 11411720 kDefaultStartingSize:4096 = 4K growth_limit_:201326592 = 192M initial_size:8388608 = 8M heap_capacity:67108864 = 65536k = 1024K * 64 = 64M bitmap_size:1048576 = 1024K capacity_:536870912 = 512M size:67108864 = 65536K = 64M = non_moving_space_capacity non_moving_space_capacity:64M 1712689152 107374182 536870912 *2 =107374182 sizeof(image_header) = 140 01-01 00:15:37.568 524 524 E art : HTC++++sizeof(image_header) = 140 01-01 00:15:37.568 524 524 E art : HTC+++Image file for image heap: 15749120 vs 15566800 01-01 00:15:37.568 524 524 E art : HTC++++xxxxxend_of_bitmap: 15749120 01-01 00:15:37.568 524 524 E art : HTC++++mmap(0x70aa2000, 15568896, 0x3, 0x2, 6, 0) of file '/data/dalvik-cache/arm64/system@framework@boot.art' See process maps in the log. 01-01 00:15:37.568 524 524 E art : HTC+++++ map actual: 0x70aa2000 01-01 00:15:37.568 524 524 E art : HTC++++ bitmap size:180224bitmap offset:15568896 01-01 00:15:37.568 524 524 E art : HTC++++mmap(0x0, 180224, 0x1, 0x2, 6, 15568896) of file '/data/dalvik-cache/arm64/system@framework@boot.art' See process maps in the log. 01-01 00:15:37.568 524 524 E art : HTC+++++ map actual: 0x7fa1810000 524: zygote64 Address Kbytes PSS Dirty Swap Mode Mapping // 0x12c00000 = 300M // capacity_:536870912 = 512M = 2084k + 522204k main_mem_map_1 0000000012c00000 2084 558 548 0 rw--- dalvik-main space (deleted) 0000000012e09000 522204 0 0 0 ----- dalvik-main space (deleted) // capacity_:536870912 = 512M = 4k + 524284k main_mem_map_2 0000000032c00000 4 0 0 0 rw--- dalvik-main space 1 (deleted) 0000000032c01000 524284 0 0 0 ----- dalvik-main space 1 (deleted) empty:478M //Align(15566800, 4K) = 15204k = 14.8M (其中0~11M对应bitmap) 0000000070aa2000 15204 827 244 0 rw--- system@framework@boot.art /////////// // Align(81015552, 4k) = (38044 + 41072 + 4) * 1024 = 77.3M 000000007197b000 38044 4170 0 0 r---- boot.oat 0000000073ea2000 41072 1463 0 0 r-x-- boot.oat 00000000766be000 4 4 0 0 rw--- boot.oat // requested_alloc_space_begin:0x766bf000 // size:67108864 = 64M = 65536K = 1760k + 4k + 55584k + 8188k 00000000766bf000 1760 148 88 0 rw--- dalvik-zygote space (deleted) 0000000076877000 4 4 4 0 rw--- dalvik-non moving space (deleted) 0000000076878000 55584 0 0 0 ----- dalvik-non moving space (deleted) 0000000079ec0000 8188 0 0 0 rw--- dalvik-non moving space (deleted) // = 524288K = 512M 000000007a6bf000 524288 491 0 0 rw--- dalvik-free list large object space (deleted) 00000055587b7000 20 0 0 0 r-x-- app_process64 00000055587cb000 4 0 0 0 r---- app_process64 00000055587cc000 4 0 0 0 rw--- app_process64 000000555ed55000 29312 1448 436 0 rw--- [heap] 0000007f8d552000 8192 0 0 0 rw--- dalvik-allocspace main rosalloc space mark-bitmap 3 (deleted) 0000007f8dd52000 8192 0 0 0 rw--- dalvik-allocspace main rosalloc space live-bitmap 3 (deleted) 0000007f8e552000 102400 0 0 0 ----- [anon] 0000007f94952000 8 4 0 0 r-x-- libwebviewchromium_loader.so .................. 0000007f9b8e8000 4 0 0 0 r---- [anon:linker_alloc] 0000007f9b8e9000 4 0 0 0 r---- [anon] 0000007f9b8ea000 240 102 0 0 r--s- framework-res.apk 0000007f9b926000 68 2 0 0 rw--- [anon:libc_malloc] 0000007f9b937000 128 4 4 0 rw--- dalvik-LinearAlloc (deleted) 0000007f9b957000 24 0 0 0 r-x-- libged.so 0000007f9b95d000 60 0 0 0 ----- [anon] 0000007f9b96c000 4 0 0 0 r---- libged.so ................. 0000007f9bae7000 92 3 0 0 rw--- [anon:libc_malloc] 0000007f9bf0e000 128 4 4 0 rw--- dalvik-rosalloc page map (deleted) 0000007f9bf2e000 22568 185 0 0 r--s- icudt55l.dat 0000007f9d538000 128 4 0 0 rw--- dalvik-LinearAlloc (deleted) 0000007f9d558000 328 88 0 0 r-x-- libjavacore.so 0000007f9d5aa000 64 0 0 0 ----- [anon] 0000007f9d5ba000 8 0 0 0 r---- libjavacore.so 0000007f9d5bc000 12 4 4 0 rw--- libjavacore.so 0000007f9d5bf000 4 0 0 0 rw--- [anon] 0000007f9d5c0000 8 4 4 0 rw--- dalvik-indirect ref table (deleted) 0000007f9d5c2000 800 0 0 0 rw--- dalvik-indirect ref table (deleted) 0000007f9d68a000 800 4 4 0 rw--- dalvik-indirect ref table (deleted) 0000007f9d752000 8 0 0 0 rw--- dalvik-mark sweep sweep array free buffer (deleted) 0000007f9d754000 8 0 0 0 rw--- dalvik-mark sweep sweep array free buffer (deleted) 0000007f9d756000 8 0 0 0 rw--- dalvik-mark sweep sweep array free buffer (deleted) 0000007f9d758000 8196 233 224 0 rw--- dalvik-live stack (deleted) 0000007f9df59000 8196 0 0 0 rw--- dalvik-allocation stack (deleted) // mark stack 0000007f9e75a000 256 0 0 0 rw--- dalvik-mark stack (deleted) // card table 0000007f9e79a000 13272 36 36 0 rw--- dalvik-card table (deleted) // LOS INFO 0000007f9f490000 1024 1 0 0 rw--- dalvik-large object free list space allocation info map (deleted) 0000007f9f590000 128 0 0 0 rw--- dalvik-large marked objects (deleted) 0000007f9f5b0000 128 0 0 0 rw--- dalvik-large live objects (deleted) // memory 512M => live bitmap 8M = 512/64 M 0000007f9f5d0000 8192 0 0 0 rw--- dalvik-allocspace main rosalloc space 1 mark-bitmap 2 (deleted) 0000007f9fdd0000 8192 0 0 0 rw--- dalvik-allocspace main rosalloc space 1 live-bitmap 2 (deleted) 0000007fa05d0000 128 0 0 0 rw--- dalvik-rosalloc page map (deleted) 0000007fa0feb000 4 0 0 0 ----- [anon] 0000007fa0fec000 16 0 0 0 rw--- [anon:thread signal stack] 0000007fa0ff0000 4 0 0 0 ----- [anon] 0000007fa0ff1000 16 0 0 0 rw--- [anon:thread signal stack] 0000007fa0ff5000 4 0 0 0 ----- [anon] 0000007fa0ff6000 16 0 0 0 rw--- [anon:thread signal stack] 0000007fa0ffa000 4 0 0 0 ----- [anon] 0000007fa0ffb000 16 0 0 0 rw--- [anon:thread signal stack] 0000007fa0fff000 4 0 0 0 ----- [anon] 0000007fa1000000 4 0 0 0 ----- [anon] 0000007fa1001000 1036 8 8 0 rw--- [stack:5606] 0000007fa1104000 8 4 4 0 rw--- dalvik-indirect ref table (deleted) 0000007fa1106000 4 0 0 0 ----- [anon] 0000007fa1107000 4 0 0 0 ----- [anon] 0000007fa1108000 1036 8 8 0 rw--- [stack:5605] 0000007fa120b000 8 4 4 0 rw--- dalvik-indirect ref table (deleted) 0000007fa120d000 4 0 0 0 ----- [anon] 0000007fa120e000 4 0 0 0 ----- [anon] 0000007fa120f000 1036 8 8 0 rw--- [stack:5604] 0000007fa1312000 8 4 4 0 rw--- dalvik-indirect ref table (deleted) 0000007fa1314000 4 0 0 0 ----- [anon] 0000007fa1315000 4 0 0 0 ----- [anon] 0000007fa1316000 1036 8 8 0 rw--- [stack:5603] 0000007fa1419000 8 4 4 0 rw--- dalvik-indirect ref table (deleted) 0000007fa141b000 4 0 0 0 rw--- dalvik-mod union bitmap (deleted) 0000007fa141c000 1000 0 0 0 rw--- dalvik-allocspace non moving space mark-bitmap 4 (deleted) 0000007fa1516000 1000 0 0 0 rw--- dalvik-allocspace non moving space live-bitmap 4 (deleted) 0000007fa1610000 1024 0 0 0 rw--- non moving space mark-bitmap 0 (deleted) 0000007fa1710000 1024 0 0 0 rw--- non moving space live-bitmap 0 (deleted) 0000007fa1810000 176 15 0 0 r---- system@framework@boot.art ////////////// 0000007fa183c000 4 0 0 0 r-x-- libsigchain.so 0000007fa183d000 60 0 0 0 ----- [anon] 0000007fa184c000 4 0 0 0 r---- libsigchain.so 0000007fa184d000 4 0 0 0 rw--- libsigchain.so 0000007fa184e000 6064 1197 0 0 r-x-- libart.so 0000007fa1e3a000 60 0 0 0 ----- [anon] 0000007fa1e49000 76 2 0 0 r---- libart.so 0000007fa1e5c000 8 8 8 0 rw--- libart.so 0000007fa1e5e000 12 4 4 0 rw--- [anon] 0000007fa1e61000 4 2 0 0 r---- boot.oat 0000007fa1e62000 4 0 0 0 r---- [anon:linker_alloc] 0000007fa1e63000 4 0 0 0 rw--- [anon:linker_alloc_vector] 0000007fa1e64000 8 4 4 0 r---- [anon:linker_alloc] 0000007fa1e66000 4 0 0 0 r--s- setfil 0000007fa1e67000 12 0 0 0 r---- [anon] mutian@mutian:~/test/test$ ll total 94508 -rw-r--r-- 1 mutian mutian 15749120 Mar 28 19:17 system@framework@boot.art -rw-r--r-- 1 mutian mutian 81015552 Mar 28 19:18 system@framework@boot.oat 15749120 = 15380k 0020 aa70 => 70aa2000 image_begin_ d087 ed00 => 00ed87d0 = 15566800 = image_size_ 00f0 6b76 => 766bf000 It must be requested_alloc_space_begin 00b0 9771 => 7197b000 oat_file_begin_ 00f0 6b76 => 766bf000 oat_file_end_ is the begin of requested_alloc_space_begin 0000000: 6172 740a 3031 3700 0020 aa70 d087 ed00 art.017.. .p.... 0000010: efa4 7d4d 00b0 9771 00c0 9771 0cd0 6b76 ..}M...q...q..kv 0000020: 00f0 6b76 0020 aa00 58c0 2671 0800 0000 ..kv. ..X.&q.... 0000030: 0100 0000 0000 0000 0821 ae00 0821 ae00 .........!...!.. 0000040: 5087 0800 58a8 b600 e825 3000 40ce e600 P...X....%0.@... 0000050: 90b9 0600 0090 ed00 00c0 0200 f0ec 9071 ...............q 0000060: 0000 0000 28ed 9071 0000 0000 60ed 9071 ....(..q....`..q 0000070: 0000 0000 98ed 9071 0000 0000 d0ed 9071 .......q.......q 0000080: 0000 0000 08ee 9071 0000 0000 0000 0000 .......q........ 0000090: 60b2 2b71 0000 0000 510d 0000 48b5 2b71 `.+q....Q...H.+q 00000a0: d0b5 2b71 58b6 2b71 e0b6 2b71 68b7 2b71 ..+qX.+q..+qh.+q 00000b0: 40b0 2b71 0000 0000 08ee 4e71 f0b7 2b71 @.+q......Nq..+q
class PACKED(4) ImageHeader { public: ImageHeader() : compile_pic_(0) {} ImageHeader(uint32_t image_begin, uint32_t image_size_, ImageSection* sections, uint32_t image_roots, uint32_t oat_checksum, uint32_t oat_file_begin, uint32_t oat_data_begin, uint32_t oat_data_end, uint32_t oat_file_end, uint32_t pointer_size, bool compile_pic_); enum ImageMethod { kResolutionMethod, //用来描述一个还未进行解析和链接的ART方法 kImtConflictMethod, kImtUnimplementedMethod, kCalleeSaveMethod, //用来描述一个由被调用者保存的r4-r11、lr和s0-s31寄存器的ART方法,即由被调用者保存非参数使用的通用寄存器以及所有的浮点数寄存器。 kRefsOnlySaveMethod, //用来描述一个由被调用者保存的r5-r8、r10-r11和lr寄存器的ART方法,即由被调用者保存非参数使用的通用寄存器。 kRefsAndArgsSaveMethod, //用来描述一个由被调用者保存的r1-r3、r5-r8、r10-r11和lr寄存器的ART方法,即由被调用者保存参数和非参数使用的通用寄存器。 kImageMethodsCount, // Number of elements in enum. }; enum ImageRoot { kDexCaches, kClassRoots, kImageRootsMax, }; enum ImageSections { kSectionObjects, kSectionArtFields, kSectionArtMethods, kSectionInternedStrings, kSectionImageBitmap, kSectionCount, // Number of elements in enum. }; ArtMethod* GetImageMethod(ImageMethod index) const; void SetImageMethod(ImageMethod index, ArtMethod* method); const ImageSection& GetImageSection(ImageSections index) const; const ImageSection& GetMethodsSection() const { return GetImageSection(kSectionArtMethods); } mirror::Object* GetImageRoot(ImageRoot image_root) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::ObjectArray<mirror::Object>* GetImageRoots() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void RelocateImage(off_t delta); bool CompilePic() const { return compile_pic_ != 0; } private: static const uint8_t kImageMagic[4]; static const uint8_t kImageVersion[4]; uint8_t magic_[4]; // Image文件魔数,固定为'art\n' uint8_t version_[4]; // Image文件版本号,目前设置为'005\0' // Required base address for mapping the image. uint32_t image_begin_; // Image size, not page aligned. uint32_t image_size_; // Checksum of the oat file we link to for load time sanity check. uint32_t oat_checksum_; //与Image文件关联的boot.art@classes.oat文件的检验值。 // Start address for oat file. Will be before oat_data_begin_ for .so files. uint32_t oat_file_begin_; //与Image文件关联的boot.art@classes.oat文件映射到内存的起始位置。 // Required oat address expected by image Method::GetCode() pointers. uint32_t oat_data_begin_; //与Image文件关联的boot.art@classes.oat文件的OATDATA段映射到内存的起始位置。 // End of oat data address range for this image file. uint32_t oat_data_end_; //与Image文件关联的boot.art@classes.oat文件的OATDATA段映射到内存的结束位置。 // End of oat file address range. will be after oat_data_end_ for // .so files. Used for positioning a following alloc spaces. uint32_t oat_file_end_; //与Image文件关联的boot.art@classes.oat文件映射到内存的结束位置。 // The total delta that this image has been patched. int32_t patch_delta_; // Absolute address of an Object[] of objects needed to reinitialize from an image. uint32_t image_roots_; //一个Object对象地址数组地址,这些Object对象就是在Image Space上分配的对象。 // Pointer size, this affects the size of the ArtMethods. uint32_t pointer_size_; // Boolean (0 or 1) to denote if the image was compiled with --compile-pic option const uint32_t compile_pic_; // Image sections ImageSection sections_[kSectionCount]; // Image methods. uint64_t image_methods_[kImageMethodsCount]; friend class ImageWriter; };
每次Heap类的成员函数PreZygoteFork被调用时,都会调用成员函数CollectGarbage执行一次垃圾收集,也就是Zygote进程每次fork子进程之前,都执行一次垃圾收集,这样就可以使得fork出来的子进程有一个紧凑的堆空间。
在划分Zygote Space之前,先将保存在Allocation Stack里面的对象标记到对应的Space的Live Bitmap去,这是通过调用Heap类的成员函数FlushAllocStack来实现的。对于新分配的对象,ART运行时不像Dalvik虚拟机一样,马上就将它们标记对应的Space的Live Bitmap中去,而是将它们记录在Allocation Stack。这样做是为了可以执行Sticky Mark Sweep垃圾收集。 Heap类的成员函数FlushAllocStack首先调用另外一个成员函数MarkAllocStack将保存在Allocation Stack里面的对象标记到对应的Space的Live Bitmap去。注意,这时候Zygote进程只有三个Space,分别是Image Space、Zygote Space和Large Object Space。其中,Image Space是不能用来分配新对象的,因此,保存在Allocation Stack里面的对象要么是在Zygote Space上分配的,要么是Large Object Space上分配的。这时候就只需要将Zygote Space和Large Object Space的Live Bitmap取出来,连同Allocation Stack一起,传递给Heap类的成员函数MarkAllocStack,记它进行相应的标记。
划分之前,我们首先明确,Heap类的成员变量alloc_space_指向的实际上就是Zygote Space,但是接下来我们要将它指向Allocation Space,因此就先把Heap类的成员变量alloc_space_保存在本地变量zygote_space中。从Zygote Space划分出一个Allocation Space的操作是通过调用DlMallocSpace类的成员函数CreateZygoteSpace来实现。DlMallocSpace类的成员函数CreateZygoteSpace返回来的是新划分出来的Allocation Space,因此这时候就将它保存在Heap类的成员变量alloc_space_中了。
当Zygote进程在fork第一个应用程序进程之前,会将已经使用了的那部分堆内存划分为一部分,还没有使用的堆内存划分为另外一部分。前者就称为Zygote堆,后者就称为Active堆。以后无论是Zygote进程,还是应用程序进程,当它们需要分配对象的时候,都在Active堆上进行。这样就可以使得Zygote堆尽可能少地被执行写操作,因而就可以减少执行写时拷贝的操作。在Zygote堆里面分配的对象其实主要就是Zygote进程在启动过程中预加载的类、资源和对象了。这意味着这些预加载的类、资源和对象可以在Zygote进程和应用程序进程中做到长期共享。这样既能减少拷贝操作,还能减少对内存的需求。
mspace_: 和Dalvik虚拟机一样,ART运行时也是将Zygote Space和Allocation Space使用的匿名共享内存块封装成一个mspace对象,以便可以使用C库提供的内存管理接口来在上面分配和释放内存。
Dalvik虚拟机并不是直接管理这块匿名共享内存,而是将它封装成一个mspace,交给C库来管理。mspace是libc中的概念,我们可以通过libc提供的函数create_mspace_with_base创建一个mspace,然后再通过mspace_开头的函数管理该mspace。例如,我们可以通过mspace_malloc和mspace_bulk_free来在指定的mspace中分配和释放内存。实际上,我们在使用libc提供的函数malloc和free分配和释放内存时,也是在一个mspace进行的,只不过这个mspace是由libc默认创建的。
在Image Space上分配的对象对在Zygote Space和Allocation Space上分配的对象的引用的Mod Union Table,以及在Zygote Space上分配的对象对在Allocation Space上分配的对象的引用的Mod Union Table。前一个Mod Union Table使用ModUnionTableToZygoteAllocspace类来描述,后一个Mod Union Table使用ModUnionTableCardCache类来描述。
如果ART运行时启动时指定了-XX:IgnoreMaxFootprint选项,即Heap类的成员变量ignore_max_footprint_的值等于true,那么就需要调用Heap类的成员函数SetIdealFootprint将Heap类的成员变量max_allowed_footprint_的值设置为size_t类型的最大值,即不对堆的大小进行限制。同时也会将Heap类的成员变量concurrent_start_bytes_设置为成员变量max_allowed_footprint_的值,这意味着不会触发并行GC。
================================================== -rw-r--r-- 1 mutian mutian 15749120 Apr 3 15:38 system@framework@boot.art -rw-r--r-- 1 mutian mutian 81015552 Apr 3 15:38 system@framework@boot.oat image space: sizeof(image_header) = 140 uint64_t image_file_size = static_cast<uint64_t>(file->GetLength()); image_file_size = 15749120 image_header.GetImageSize() = 15566800 15749120 = Align(15566800, 4K) + 176k mmap(0x6f7fc000, 15568896, 0x3, 0x2, 6, 0) of file '/data/dalvik-cache/arm64/system@framework@boot.art' 15568896 = Align(15566800, 4K) mmap(0x0, 180224, 0x1, 0x2, 6, 15568896) of file '/data/dalvik-cache/arm64/system@framework@boot.art' image bitmap 180224 = 176K //create ContinuousSpaceBitmap, only 11M has 176k bitmap accounting::ContinuousSpaceBitmap::CreateFromMemMap() name:imagespace /data/dalvik-cache/arm64/system@framework@boot.art live-bitmap 0, heap_capacity:11534336 = 11M 11534336 = 176K * 64 = 11M heap_capacity:11534336=11M, bitmap_size:180224=176K image space SpaceType:0 GcRetentionPolicy:0 bitmap_index:0 kSectionObjects .Offset():0 image_header.GetImageSection(ImageHeader::kSectionObjects).End(): 11411720 kSectionArtFields .Offset():11411720 image_header.GetImageSection(ImageHeader::kSectionArtFields).End(): 11970648 kSectionArtMethods .Offset():11970648 image_header.GetImageSection(ImageHeader::kSectionArtMethods).End(): 15126080 kSectionInternedStrings .Offset():15126080 image_header.GetImageSection(ImageHeader::kSectionInternedStrings).End(): 15566800 kSectionImageBitmap .Offset():15568896 image_header.GetImageSection(ImageHeader::kSectionImageBitmap).End(): 15749120 ----------------------------------------- non_moving_space_mem_map: non_moving_space_capacity:67108864 = 64M requested_alloc_space_begin: address after boot.oat non_moving_space_mem_map.reset(MemMap::MapAnonymous(space_name, requested_alloc_space_begin, non_moving_space_capacity, PROT_READ | PROT_WRITE, true, false, &error_str)); //absolute address = 300M main_mem_map_1, main_mem_map_2 capacity_:536870912=512M -------- non_moving_space_ = space::DlMallocSpace::CreateFromMemMap(non_moving_space_mem_map.release(), "zygote / non moving space", kDefaultStartingSize, initial_size, size, size, false); DlMallocSpace* DlMallocSpace::CreateFromMemMap(MemMap* mem_map, const std::string& name, size_t starting_size, size_t initial_size, size_t growth_limit, size_t capacity, bool can_move_objects) { kDefaultStartingSize:4096 = 4K initial_size:8388608 = 8M size = 64M non_moving_space_ SpaceType:1 GcRetentionPolicy:1 main_space_: CreateMainMallocSpace(main_mem_map_1.release(), initial_size, growth_limit_, capacity_); initial_size:8388608=8M growth_limit_:201326592=192M capacity_ =512M SpaceType:1 GcRetentionPolicy:1 live_bitmap_ mark_bitmap_ main_space_backup_: same as main_space_ main_space_backup_.reset(CreateMallocSpaceFromMemMap(main_mem_map_2.release(), initial_size, growth_limit_, capacity_, name, true)); SpaceType:1 GcRetentionPolicy:1 live_bitmap_ mark_bitmap_ large_object_space_: large_object_space_ = space::FreeListSpace::Create("free list large object space", nullptr, capacity_); capacity_:512M SpaceType:4 GcRetentionPolicy:1