67 基于lldb分析运行时数据

Posted 蓝风9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了67 基于lldb分析运行时数据相关的知识,希望对你有一定的参考价值。

前言

呵呵, 之前一直对于 内存这个词语 说陌生吧, 又有一定的了解(课本上, 书籍中, 别人口中), 但是 很少有一个直接能够了解的机会, 呵呵 只从自从之前请教一位朋友使用 lldb 的调试之后, 感觉对于 内存有了一些 更加直观的感受吧, 呵呵 

这里 就借用一些简单的 c程序片段, java测试脚本 来了解一下吧 

inspect bVar

首先是测试脚本 

//
// Created by Jerry.X.He on 2020-01-30.
//

#include <iostream>
#include "stdio.h"
using namespace std;

int main() {

    bool bVar = true;
    bool bVar02 = false;
    cout << " bVar : " << bVar << endl;
    printf(" bVar : %d \\n ", bVar);

    return 0;

}

当然, 这里的程序输出, 其实我们并不是很关系, 我们关心的是相关调试信息 

(lldb) p bVar
(bool) $2 = true
(lldb) p &bVar
(bool *) $3 = 0x00007ffeee28182b
(lldb) p bVar02
(bool) $4 = false
(lldb) p &bVar02
(bool *) $5 = 0x00007ffeee28182a
(lldb) x 0x00007ffeee28182a
0x7ffeee28182a: 00 01 00 00 00 00 48 18 28 ee fe 7f 00 00 d5 c3  ......H.(.......
0x7ffeee28183a: 3e 73 ff 7f 00 00 d5 c3 3e 73 ff 7f 00 00 00 00  >s......>s......
(lldb) p bVar02 = true 
(bool) $6 = true
(lldb) x 0x00007ffeee28182a
0x7ffeee28182a: 01 01 00 00 00 00 48 18 28 ee fe 7f 00 00 d5 c3  ......H.(.......
0x7ffeee28183a: 3e 73 ff 7f 00 00 d5 c3 3e 73 ff 7f 00 00 00 00  >s......>s......

可以看到 bVar, bVar02 在内存中占用1个字节, 当程序更新了对应的值的时候, 内存存储的数据发生了改变 

inspect Oop

创建了一个 Object, "com.hx.test03.Test05CloneCallObjectConstructor", 继承自 java.lang.Object, 没有其他的任何的字段, 占用16个字节
obj()->incr_age() 调用两次, 分别查看对应的内存的数据

测试代码如下 

package com.hx.test03;

/**
 * CloneCallObjectConstructor
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2019-12-29 14:41
 */
public class Test05CloneCallObjectConstructor implements Cloneable {

  // Test05CloneCallObjectConstructor
  public static void main(String[] args) throws Exception {

    Test05CloneCallObjectConstructor obj = new Test05CloneCallObjectConstructor();
    Test05CloneCallObjectConstructor cloned = (Test05CloneCallObjectConstructor) obj.clone();

    System.out.println(obj == cloned);

  }

}


打上断点, 监控对象 obj   

(lldb) p obj()
(oop) $1 = 0x00000007bf050050
(lldb) x 0x00000007bf050050
0x7bf050050: 01 00 00 00 00 00 00 00 86 1f 01 f8 00 00 00 00  ................
0x7bf050060: be ba ad ba be ba ad ba be ba ad ba be ba ad ba  ................
(lldb) p obj()->klass()
(InstanceKlass *) $2 = 0x00000007c008fc30
(lldb) e obj()->incr_age()
(lldb) x 0x00000007bf050050
0x7bf050050: 09 00 00 00 00 00 00 00 86 1f 01 f8 00 00 00 00  ................
0x7bf050060: be ba ad ba be ba ad ba be ba ad ba be ba ad ba  ................
(lldb) e obj()->incr_age()
(lldb) x 0x00000007bf050050
0x7bf050050: 11 00 00 00 00 00 00 00 86 1f 01 f8 00 00 00 00  ................
0x7bf050060: be ba ad ba be ba ad ba be ba ad ba be ba ad ba  ................

Test05CloneCallObjectConstructor 在我这里 64bit vm, 默认开启了 UseCompressedOops 

一个 Test05CloneCallObjectConstructor 占用 16个字节, 8个字节 markoop, 4个字节的 compressed_klass, 4个字节的 align 填充 

如果你看过 04 对象的默认布局 你应该能明白 compressed_klass 的数据存储 和 obj()->klass() 的关系 

接下来我们看下 markoop 的这 8个 字节 

// mark oop 数据分布如下, 来自于 markOop.hpp
//  32 bits:
//  --------
//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
//             size:32 ------------------------------------------>| (CMS free block)
//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
//  64 bits:
//  --------
//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
//  size:64 ----------------------------------------------------->| (CMS free block)

数据拆解如下, 我们可以发现 age 的逻辑意义在 incr_age 的调用过程中变化了 

// age + biased_lock, lock
0x01 -> 0b 0000 0 01
0x09 -> 0b 0001 0 01
0x11 -> 0b 0010 0 01

完 

以上是关于67 基于lldb分析运行时数据的主要内容,如果未能解决你的问题,请参考以下文章

AVCaptureSession 运行时崩溃。致命错误:在展开可选值 (lldb) 时意外发现 nil

运行单变量生存分析时出错

lldb调试命令

SWIFT 致命错误:在展开可选值 (lldb) 时意外发现 nil

LLDB 不显示源代码

常用 LLDB 命令