对象的创建
1、指针碰撞:假设 java 堆中的内存是绝对规整的,所有被使用过的内存都放到一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就是仅仅把那个指针向空闲空间方向挪动一段与对象大小相等的距离。这种分配方法称为“指针碰撞”。2、空闲列表:如果内存并不是规整的,已被使用的和空闲的内存交互在一起,没有办法进行简单的指针碰撞,虚拟机就维护一个列表,记录哪些内存块是可用的,在分配的时候从列表中找到一块足够大的内存块划分给实例对象,并更新列表上的记录。这种分配方式叫做 “空闲列表”。选用哪种分配方式由Java堆是否完整来决定,而Java堆是否完整又取决于所采用的垃圾收集器广电大流量卡是否带有空间压缩的能力来决定的。Serial、ParNew等压缩整理过程的收集器就使用“指针碰撞”,基于CMS这种清除算法就使用“空闲列表”。
并发情况下线程不是安全的:
1、CAS + 失败重试,保证原子操作。2、本地线程分配缓冲 ( TLAB ):把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存 ,成为本地线程分配缓冲,哪个线程要分配内存,就在哪个线程的本地缓冲区中分配。对象的内存布局
在Hotspot虚拟机里,对象在堆内存中的存储布局可以分为三个部分:对象头、实例数据、对齐填充。
对象头包含两部分:
1、Mark Word哈希码(HashCode);GC广电大流量卡分代年龄;锁相关信息(锁状态标志、线程持有的锁、偏向线程ID)。2、类型指针:类型元数据的指针,来确定它是哪个类的实例。如果对象是数组,对象头中还有记录数组长度的数据。实例数据即我们代码中定义的各种类型字段的内容。
对象的访问定位
创建对象自然是为了后续使用该对象,Java 程序会通过栈上的reference数据来操作栈上的具体对象。
主流的访问方式主要有句柄和直接指针:
1、句柄:Java堆中将分出一块内存作为句柄池,reference中存储的就是对象的句柄地址,而句柄中又包含了对象实例数据和对象类型数据各自的地址信息。2、直接指针:reference中存储的就是对象地址。使用句柄来访问的最大好处就广电大流量卡是reference中存储的是 稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的)时只需要改变句柄中的实例数据指针,而reference本身不需要修改。
使用直接指针的好处就是速度更快,他节省了一次指针定位的时间开销(HotSpot虚拟机主要采取的是这种对象访问定位)。
内存分配策略
Java堆是垃圾收集器管理的主要区域,因此也被称作GC堆(Garbage Collected Heap)。从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以Java堆还可以细分为:新生代和老年代。再细致一点有:Eden 空间、From Survivor、To Survivor 空间等。
进一步划广电大流量卡分的目的是更好地回收内存,或者更快地分配内存。
Java堆的空间基本结构:
Eden 区、From Survivor0(“From”) 区、To Survivor1(“To”) 区都属于新生代,Old Memory 区属于老年代。
大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入s0或者s1,并且对象的年龄还会加1(Eden区->Survivor区后对象的初始年龄变为1),当它的年龄增加到一定程度(默认为15岁),就会被晋升到老年代中。
大对象直接进入老年代
大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。
为什么要这样呢? 为了避免为大对象分配内广电大流量卡存时由于分配担保机制带来的复制而降低效率。
针对 HotSpot VM 的实现,它里面的 GC 其实准确分类只有两大种:
部分收集(Partial GC):
1、新生代收集(Minor GC / Young GC):只对新生代进行垃圾收集;2、老年代收集(Major GC / Old GC):只对老年代进行垃圾收集。需要注意的是 Major GC在有的语境中也用于指代整堆收集;3、混合收集(Mixed GC):对整个新生代和部分老年代进行垃圾收集。整堆收集(Full GC):收集整个 Java 堆和方法区。
对象已死 ?
引用计数算法:在对象中添加一个引用计数器,每当有一个地方引用它,计数器加一,当引用广电大流量卡失效时,计算器就减一。任何时刻计算器为零的对象都不可以再被使用。(无法解决循环引用)
可达性分析算法:如果某个对象到GCRoots没有任何引用链相连,或者用图论的话是从GCRoots到这个对象不可达,则证明这个对象是不可能再被使用的。
引用计数法
给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1;当引用失效,计数器就减1;任何时候计数器为0的对象就是不可能再被使用的。
这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题。
友情提醒: 请添加客服微信进行免费领取流量卡!
QQ交流群:226333560 站长微信:qgzmt2
原创文章,作者:sunyaqun,如若转载,请注明出处:https://www.dallk.cn/16390.html