1 前言

目录

1 前言

2 一个NSObject占用多少内存

3 为什么呢 ?

4 如何在内存中看呢?


OC 的面向对象都是基于C/C++ 的数据结构实现的

结构体

2 clang 命令转换成c++ 代码

clang -rewrite-objc main.m -o main.cpp

以上的命令是不分平台进行编译的,main.cpp 代码有9万多行,如果指定用iphone 的话,用以下的命令,编译之后有3万多行代码

xcrun -sdk iphoneos clang  -arch arm64 -rewrite-objc main.m -o main.cpp

int main(int argc, const char * argv[]) {/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; NSObject *obj = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"));}return 0;
}

4 NSObject 的本质

在c++代码中这是NSObject的实现

NSObject_IMPL 就是意味着 NSObject 的 Implementation

struct NSObject_IMPL {
    Class isa;
};

2 一个NSObject占用多少内存

1 按道理来讲,一个NSObject 本质就是一个结构体,其中的一个isa 指针在64位中是占据8个字节的

实际是16个字节的

NSObject *obj = [[NSObject alloc]init];

利用runtime 中的 class_getInstanceSize 获取大小

// 以下打印结果是8  ,以下代码的含义就是获取一个类的实例对象的大小

NSLog(@"%zu",class_getInstanceSize([NSObject class]));

导入 #import <malloc/malloc.h>

// 打印结果是 16,以下代码的含义是获取这个指针所指向内存的大小

NSLog(@"%zu",malloc_size((__bridge const void *)(obj)

所以这样来讲,如果问一个NSObject 对象占用多少内存,或者分配多少内存,就是16个字节

如果问 一个NSObject 对象实际是多大的内存,就是8个字节

3 为什么呢 ?

首先我们打开苹果开源的代码,找到代码一步步分析,找到最新的objc 代码下载分析

https://opensource.apple.com/tarballs/objc4/

打开下载的工程文件 搜索allocWithZone(alloc本质调用的还是这个方法)

以下是源代码调用的顺序

源码调用顺序// Replaced by ObjectAlloc
+ (id)allocWithZone:(struct _NSZone *)zone {return _objc_rootAllocWithZone(self, (malloc_zone_t *)zone);
}id
_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone)
{id obj;if (fastpath(!zone)) {obj = class_createInstance(cls, 0);} else {obj = class_createInstanceFromZone(cls, 0, zone);}if (slowpath(!obj)) obj = _objc_callBadAllocHandler(cls);return obj;
}id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone)
{void *bytes;size_t size;// Can't create something for nothingif (!cls) return nil;// Allocate and initializesize = cls->alignedInstanceSize() + extraBytes;// CF requires all objects be at least 16 bytes.if (size < 16) size = 16;if (zone) {bytes = malloc_zone_calloc((malloc_zone_t *)zone, 1, size);} else {bytes = calloc(1, size);}return objc_constructInstance(cls, bytes);
}// 内部有一个方法  instanceSize, 当内存不足16的时候,直接返回16inline size_t instanceSize(size_t extraBytes) const {if (fastpath(cache.hasFastInstanceSize(extraBytes))) {return cache.fastInstanceSize(extraBytes);}size_t size = alignedInstanceSize() + extraBytes;// CF requires all objects be at least 16 bytes.if (size < 16) size = 16;return size;}

函数调用顺序。allocWithZone - >  objc_rootAllocWithZone -> class_createInstanceFromZone -> instanceSize(内部分配内存的方法)

说结论吧,内部调用了一个方法 instanceSize 方法 ,内存不足16,直接返回16 。

至于instance 方法内部又去调用了alignedInstanceSize 方法,这个方法其实返回的就是8,为什么呢? 因为isa 指针的大小就是8,说的很明白就是成员变量的大小

// Class's ivar size rounded up to a pointer-size boundary.
    uint32_t alignedInstanceSize() const {
        return word_align(unalignedInstanceSize());
    }

4 如何在内存中看呢?

获取 obj 的内存地址

在控制台中 打印

memory read 0x100664d00  这个地址,然后就是打印出,也是连续的16个字节

0x100664d00: 19 c1 02 95 ff ff 1d 00 00 00 00 00 00 00 00 00

用以下明令也是可以的

x  0x100664d00

1 OC 对象的本质(一个NSObject 对象占用的内存大小)相关推荐

  1. 获取内存_如何获取一个进程所占用的内存

    推荐观看: BATJ面试官最喜欢问的:多线程.线程并发面试题详解(volatile+ThreadLocal+Sleep)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili. ...

  2. 2 OC 对象的本质(一个Student 占用的内存大小)

    一 Student 占用的内存空间 补充: 1 成员变量占用字节的大小: 2 内存对齐的规则:结构体的内存大小必须是最大成员变量的内存的倍数. 一个 Student 类,继承自NSObject,有两个 ...

  3. 一个NSObject对象占多少内存?

    以下都是在64bit环境下操作: 我们平时编写的Objective-C代码,底层实现其实都是C\C++代码 在这里我们将main.m 使用clang转成c++文件,也就是在终端输入 xcrun -sd ...

  4. java创建response对象_创建一个HttpResponse对象

    创建一个HttpResponse对象 HttpResponse类实现了javax.servlet.http.HttpServletResponse.跟随它的是一个叫做 HttpResponseFaca ...

  5. java取得对象占用的内存大小

    本文环境 win 10 jdk 1.8.0_241 IntelliJ 2019.1.3 一.通过Instrumentation获取内存 在java工程中添加如下代理类: package com.nin ...

  6. 一个程序最多能占用的内存大小

    因为内存资源总是稀缺的,即便在拥有百 G 内存的机器上,我们都可以轻易把内存填满.为了解决这个问题,就需要用到虚拟化技术. GC 是面试的高频重点知识,同时也是程序员日常开发需要理解的部分.学习 GC ...

  7. AutoMapper多个对象映射到一个Dto对象

    一.定义源映射对象 为了体现AutoMapper映射特性,在SocialAttribute中的Name属性没有定义在People中,People的Ear属性也不存在与SocialAttribute和P ...

  8. java新建对象校验_验证某个对象是否是一个mock对象或者一个spy对象

    C**f回复了y**4在课程中的问题:final和自动装配... v**g添加了笔记:James Gosl... c**k向课程作业中提交了代码 我**-向课程作业中提交了代码 2**9在课程中提出了 ...

  9. 怎么测试一个java程序占用的内存和cpu消耗?

    1.测试查看单独的class的资源消耗方法. Runtime r = Runtime.getRuntime();     long freeMemory = r.freeMemory(); long ...

最新文章

  1. July大神---SVM讲解
  2. 神经网络 深度学习 专业术语解释(Step, Batch Size, Iteration,Epoch)
  3. sap tcode 功能对照表_Python for Ev3练习amp;Minstorms对照表02
  4. JAVA8后接口的新特性
  5. list vue 添加数据方法_在PySpark数据框中添加新列的5种方法
  6. 2021-08-06 MD5mysql 加密校验
  7. crossplaform---Nodejs in Visual Studio Code 04.Swig模版
  8. 舆情监测产品的过去与现在
  9. OJ密码岛 1243.谢尔宾斯基三角形
  10. VS各个版本的优缺点和发展过程(VC6.0——VS2015)
  11. excel在线_图片转Excel表格在线工具,分享几款不错的工具
  12. chm 乱码 掌阅_chm文件中文乱码问题
  13. oracle12c不使用cdb模式,Oracle 12c 使用Non-CDB来创建PDB
  14. django之csrf_exempt解决跨域请求的问题
  15. 五、NLP聊天语料处理
  16. 键盘修改器,绝对管用
  17. 什么是代码?code?
  18. 请叫我En-Tan-Mo
  19. java Instant
  20. scratch 3 安装过程图

热门文章

  1. python工具使用笔记
  2. Python maketrans() 方法
  3. SSL 1460——最小代价问题
  4. IOS类似9.png
  5. 配置MySQL主从复制
  6. Nginx源代码分析 - 日志处理
  7. C#下用P2P技术实现点对点聊天
  8. 一种准标准CSV格式的介绍和分析以及解析算法
  9. Ubuntu14.04 64位上配置终端显示git分支名称
  10. 【FFmpeg】自定义回调函数处理AVIOContext中的数据