从Java类到目的的创设进程都做了些啥?管理内存中的目的是啥样的?

iOS中category即:类别 ;extension 为扩张

先想起一下Java程序执行的历程:

一.category 

Java程序执行时,第一步系统成立虚拟机进程,然后虚拟器用类加载器Class
Loader加载java程序类文件到方法区。

花色是一种为依存的类添加新情势的章程。

方法区放什么东西?

应用Objective-C的动态运行时分配机制,Category提供了一种比持续(inheritance)更为精简的办法来对class举办扩充,无需创建对象类的子类就能为依存的类添加新措施,可以为其它已经存在的class添加方法,包括这么些并未源代码的类(如某些框架类)。

存放加载过的类音信、常量、静态变量、及jit编译后的代码(类情势)等数码的内存区域。它是线程共享的。

1.类其它受制:(1)无法向品种中添加新的实例变量,序列没有地点容纳实例变量。如果一定要添加实例变量,可以利用runtime
库objc_setAssociatedObject / objc_getAssociatedObject
函数来缓解。objc_setAssociatedObject
就是将一个对象跟另一个对象进行关联,并用一个key来标示,objc_getAssociatedObject
就是用那么些key来得到与receiver相关联的一个对象。

方法区存放的消息包括:类的基本音信、运行时常量池、变量字段新闻、方法音信等。这有的的事无巨细介绍看下面链接的稿子。

留意:必须拔取@dynamic来让编译器知道大家协调实现setter/getter方法(假如对于@dynamic有疑难,请参见:http://stackoverflow.com/questions/1160498/synthesize-vs-dynamic-what-are-the-differences)

详细Java程序运行的内存结构介绍
点此处

         不能够选取@synthesize(也不可能@dynamic
和@synthesize都不写,什么都不写在新式的xcode里是默认@synthesize),@synthesize会自动生成成员变量,并自动生成setter/getter方法。

简易过程:

类加载成功后,主线程运行static main()时在虚拟机栈中建栈帧,压栈。

推行到new Object()时,在堆heap里创立对象。

对象制造的过程就是堆上分配实例对象内容空间的进程,在堆中目的内存空间的具体社团如下:

对象头 这多少个头包括多少个部分,第一有些用以存储自身运行时的数额例如GC标志位、哈希码、锁状态等消息。第二局部存放指向方法区类静态数据的指针。

实例变量 存放类的属性数据音信,包括父类的特性音讯。淌假若数组的实例部分还包括数组的长度。那有的内存按4字节对齐。

填充数据
这是因为虚拟机要求对象先河地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为着字节对齐。HotSpot
VM的机关内存管理要求对象起先地址必须是8字节的整数倍。对象头本身是8的翻番,当目的的实例变量数据不是8的倍数,便需要填写数据来担保8字节的对齐。此外,堆上对象内存的分配是出现举办的.

接下来执行类的构造函数开头化。

Java虚拟机规范规定该区域可抛出OutOfMemoryError。

         最后,objc_setAssociatedObject 的关联的policy
可以遵照自己的要求使用,这多少个事例使用
OBJC_ASSOCIATION_RETAIN_NONATOMIC来标示一个strong
reference来指向被提到的对象。

详尽步骤

例如:

Dog dog= new Dog();

当虚拟机执行到new指令时,它先在常量池中寻觅“Dog”,看是否稳定到Dog类的标记引用;假诺能,表明这一个类已经被加载到方法区了,则继续执行。假设没有,就让Class
Loader先执行类的加载。

然后,虚拟机开端为该目的分配内存,对象所需要的内存大小在类加载成功后就曾经确定了。这时候只要在堆中按要求分配空间即可。具体分配内存时有三种模式,第一种,内存相对规整,那么一旦在被占用内存和空闲内存间放置指针即可,每趟分配空间时如果把指针向空闲内存空间移动相应距离即可,当某对象被GC回收后,则需要开展一些对象内存的迁移。第二种,空闲内存和非空闲内存夹杂在协同,那么就需要用一个列表来记录堆内存的选取状态,然后按需分配内存。

对此多线程的情事,怎么样保管一个线程分配了对象内存但尚未修改内存管理指针时,其他线程又分配该块内存而覆盖的状态?有一种方法,就是让每一个线程在堆中先预分配一小块内存(TLAB本地线程分配缓冲),每个线程只在团结的内存中分配内存。但目的自我按其访问属性是可以线程共享访问的。

内存分配到后,虚拟机将分配的内存空间都先导化为零值(不包括对象头)。实例变量按变量类型初阶化相应的默认值(数值型为0,boolan为false),所以实例变量不赋初值也能动用。接着设置对象头新闻,比如对象的哈希值,GC分代年龄等。

从虚拟机角度,此时一个新的对象已经成立完成了。但从我们程序运行的角度,新建对象才刚刚起先,对象的构造方法还未曾履行。只有执行完构造方法,按构造方法举行开始化后,对象才是干净创制完成了。

构造函数的施行还涉嫌到调用父类构造器,假诺没有显式表明调用父类构造器,则自动添加默认构造器。

到此,new运算符可以回到堆中这一个目的的引用了。

这时,会按照dog这些变量是实例变量、局部变量或静态变量的不比将引用位于不同的地点:

倘诺dog局部变量,dog变量在栈帧的局部变量表,这些目的的引用就位于栈帧。

假如dog是实例变量,dog变量在堆中,对象的引用就位于堆。

假设dog是静态变量,dog变量在方法区,对象的引用就位于方法区。

(2)名称争持,即当连串中的方法名与原始类中的名称相同的时候,体系享有更高的预先级。类另外法子将完全代替原来方法而不能再使用原有方法。

2.类另外效率

体系的效用至关重要有两个:

(1)可以将类的实现分散到六个不等的文书或者不同的框架中,方便代码的管住。也可以对框架提供类的增添(没有源码,不可能改改)。

 (2)创立对私有方法的前向引用:假如其他类中的方法未兑现,在您拜访其他类的个体方法时编译器报错这时使用项目,在类型中扬言这一个形式(不必提供格局实现),编译器就不会再暴发警告

 (3)向目的添加非正式协议:创制一个NSObject的类型称为“创造一个非正式磋商”,因为能够当做任何类的嘱托对象使用。

二.Extension 的使用

 
 首先仍然需要创造相关类的扩大,即方法的扬言,然后在需要扩张的类中引入头文件,然后实现阐明的法门。

三.Category 与Extension 的区别

1.样式上看:extension 是匿名的category

2.extension中扬言的格局需要在mainimplementation中实现,而category
不做强制要求

3.extension 方可添加属性、成员变量,而category 一般不可以。

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注