pull/6/head
yuanguangxin 4 years ago
parent 17cca86566
commit f6be04ae40

@ -345,6 +345,24 @@ JVM引入动态年龄计算主要基于如下两点考虑
4. 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
5. 由Eden区、From Space区向To Space区复制时对象大小大于To Space可用内存则把该对象转存到老年代且老年代的可用内存小于该对象大小
### TLAB
在Java中典型的对象不再堆上分配的情况有两种TLAB和栈上分配通过逃逸分析。JVM在内存新生代Eden Space中开辟了一小块线程私有的区域称作TLABThread-local allocation buffer。默认设定为占用Eden Space的1%。在Java程序中很多对象都是小对象且用过即丢它们不存在线程共享也适合被快速GC所以对于小对象通常JVM会优先分配在TLAB上并且TLAB上的分配由于是线程私有所以没有锁开销。因此在实践中分配多个小对象的效率通常比分配一个大对象的效率要高。也就是说Java中每个线程都会有自己的缓冲区称作TLABThread-local allocation buffer每个TLAB都只有一个线程可以操作TLAB结合bump-the-pointer技术可以实现快速的对象分配而不需要任何的锁进行同步也就是说在对象分配的时候不用锁住整个堆而只需要在自己的缓冲区分配即可。
### Java对象分配的过程
1. 编译器通过逃逸分析确定对象是在栈上分配还是在堆上分配。如果是在堆上分配则进入2.
2. 如果tlab_top + size <= tlab_end则在在TLAB上直接分配对象并增加tlab_top 的值如果现有的TLAB不足以存放当前对象则3.
3. 重新申请一个TLAB并再次尝试存放当前对象。如果放不下则4。
4. 在Eden区加锁这个区是多线程共享的如果eden_top + size <= eden_end则将对象存放在Eden区增加eden_top 的值如果Eden区不足以存放则5。
5. 执行一次Young GCminor collection
6. 经过Young GC之后如果Eden区任然不足以存放当前对象则直接分配到老年代。
### 对象内存分配的两种方法
1. 指针碰撞(Serial、ParNew等带Compact过程的收集器) 假设Java堆中内存是绝对规整的所有用过的内存都放在一边空闲的内存放在另一边中间放着一个指针作为分界点的指示器那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离这种分配方式称为“指针碰撞”Bump the Pointer
2. 空闲列表(CMS这种基于Mark-Sweep算法的收集器) 如果Java堆中的内存并不是规整的已使用的内存和空闲的内存相互交错那就没有办法简单地进行指针碰撞了虚拟机就必须维护一个列表记录上哪些内存块是可用的在分配的时候从列表中找到一块足够大的空间划分给对象实例并更新列表上的记录这种分配方式称为“空闲列表”Free List
### JVM类加载过程
类从被加载到虚拟机内存中开始到卸载出内存为止它的整个生命周期包括加载、验证、准备、解析、初始化、使用和卸载7个阶段。

Loading…
Cancel
Save