JVM学习(二)线程共享运行时数据区域 与 对象的内存分配

  内存区域下半场,紧接上部分,线程共享的内存部分。

java堆(java Heap)

主要用于存放对象,为几乎所有线程所共享

根据规范:java堆并不一定需要内存上连续,只需要逻辑上连续即可


在这里插入图片描述

由于使用永久代来实现方法区的话,某些情况会出现内存溢出的尴尬问题

于是1.8后更新了 ,使用 Meta space 代替永久代,解决永久代溢出的问题

具体阐述:可以参照文章 duanxz的博客中关于为什么替代掉永久代的问题
在这里插入图片描述

方法区 (Method Area alias-> Non-Heap)

主要存储类信息、常量、静态变量等数据


新对象内存的分配

  称之为一条new操作的旅程

一、类加载检查过程

首先要去检查参数能否在常量池中定位到引用,并且检测这个对象是否已被加载、解析和初始化过。

二、为该对象分配内存空间

分配内存也存在两种方法,具体系统采用的那种算法需要执行

java -XX:+PrintCommandLineFlags -version

通常附带 compact 算法的收集器 采用指针碰撞,否则使用 空闲列表


①指针碰撞

前提是java堆中内存是绝对规整的情况下(使用过与空闲的内存分明鲜别)

此时,分配空间就像切蛋糕一样轻易便可

②空闲列表

内存是零散的,虚拟机维护了一个对应空闲或使用的内存地址记录表。按需将记录内的空闲内存分配出去


三、分配内存时的并发问题

(虽然java不提指针,但是对于内存地址来说,我还是引用下)
即存在A分配0x11地址,还未把地址指向它,同时B也被指向0x11地址的问题。


①默认处理

虚拟机采用CAS 配上失败重试来保证操作的原子性

②本地线程分配缓冲(Thread Local Allocation Buffer alisa-> TLAB)

将分配内存的操作按照线程划分在不同空间内。哪个线程需要分配内存,则在在哪个线程的TLAB上按需分配,当且仅当TLAB用完同时需要分配新的TLAB时,才需要同步锁定操作(操作内属于线程私有,不需要锁,效率会提高)。

启用方法: ```-XX:+/- UseTLAB```


四、对象初始化

将分配下去的初始内存空间初始化为零值(不包含头对象)

如果采用TLAB,则可以在分配时进行初始化

对象头不被初始化是因为,要将元数据信息,GC分代等信息存储至对象头中

执行开发者意愿的初始化操作

猜你喜欢

转载自blog.csdn.net/CoffeeAndIce/article/details/90247477