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分析运行时数据的主要内容,如果未能解决你的问题,请参考以下文章