1 OC 对象的本质(一个NSObject 对象占用的内存大小)
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 对象占用的内存大小)相关推荐
- 获取内存_如何获取一个进程所占用的内存
推荐观看: BATJ面试官最喜欢问的:多线程.线程并发面试题详解(volatile+ThreadLocal+Sleep)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibiliwww.bilibili. ...
- 2 OC 对象的本质(一个Student 占用的内存大小)
一 Student 占用的内存空间 补充: 1 成员变量占用字节的大小: 2 内存对齐的规则:结构体的内存大小必须是最大成员变量的内存的倍数. 一个 Student 类,继承自NSObject,有两个 ...
- 一个NSObject对象占多少内存?
以下都是在64bit环境下操作: 我们平时编写的Objective-C代码,底层实现其实都是C\C++代码 在这里我们将main.m 使用clang转成c++文件,也就是在终端输入 xcrun -sd ...
- java创建response对象_创建一个HttpResponse对象
创建一个HttpResponse对象 HttpResponse类实现了javax.servlet.http.HttpServletResponse.跟随它的是一个叫做 HttpResponseFaca ...
- java取得对象占用的内存大小
本文环境 win 10 jdk 1.8.0_241 IntelliJ 2019.1.3 一.通过Instrumentation获取内存 在java工程中添加如下代理类: package com.nin ...
- 一个程序最多能占用的内存大小
因为内存资源总是稀缺的,即便在拥有百 G 内存的机器上,我们都可以轻易把内存填满.为了解决这个问题,就需要用到虚拟化技术. GC 是面试的高频重点知识,同时也是程序员日常开发需要理解的部分.学习 GC ...
- AutoMapper多个对象映射到一个Dto对象
一.定义源映射对象 为了体现AutoMapper映射特性,在SocialAttribute中的Name属性没有定义在People中,People的Ear属性也不存在与SocialAttribute和P ...
- java新建对象校验_验证某个对象是否是一个mock对象或者一个spy对象
C**f回复了y**4在课程中的问题:final和自动装配... v**g添加了笔记:James Gosl... c**k向课程作业中提交了代码 我**-向课程作业中提交了代码 2**9在课程中提出了 ...
- 怎么测试一个java程序占用的内存和cpu消耗?
1.测试查看单独的class的资源消耗方法. Runtime r = Runtime.getRuntime(); long freeMemory = r.freeMemory(); long ...
最新文章
- July大神---SVM讲解
- 神经网络 深度学习 专业术语解释(Step, Batch Size, Iteration,Epoch)
- sap tcode 功能对照表_Python for Ev3练习amp;Minstorms对照表02
- JAVA8后接口的新特性
- list vue 添加数据方法_在PySpark数据框中添加新列的5种方法
- 2021-08-06 MD5mysql 加密校验
- crossplaform---Nodejs in Visual Studio Code 04.Swig模版
- 舆情监测产品的过去与现在
- OJ密码岛 1243.谢尔宾斯基三角形
- VS各个版本的优缺点和发展过程(VC6.0——VS2015)
- excel在线_图片转Excel表格在线工具,分享几款不错的工具
- chm 乱码 掌阅_chm文件中文乱码问题
- oracle12c不使用cdb模式,Oracle 12c 使用Non-CDB来创建PDB
- django之csrf_exempt解决跨域请求的问题
- 五、NLP聊天语料处理
- 键盘修改器,绝对管用
- 什么是代码?code?
- 请叫我En-Tan-Mo
- java Instant
- scratch 3 安装过程图