JVM Java内存区域 与 内存溢出 (系列号1)

运行时数据区域

运行时的数据区域,就是JVM管理的内存区域。JVM 运行程序的时候,管理着运行时的内存(一般以静态的 main 方法进入本类的运行时数据区,几乎所有Java程序都是从此开始,也就是说这里的 “运行时的数据区域” 就是一个程序甚至是一个项目的内存开辟起始区,逻辑上不会有第二个与此不连通的区域了 )。JVM 将内存划分为多个不同的数据区域。这些不同的数据区域有着自己的创建和销毁时间,跟着进程或者线程的启动、结束而创建和销毁。

看看运行时的数据区域图示:

 我们分别解释一下这些不同的区域的特点:

  1. 程序计数器(这里不是 PC寄存器,写错了):内存中的很小的一个区域,用来指示字节码运行的下一条指令。注意,每个线程都会独有一个程序计数器。这样也是为了能够让线程记住自己暂停的位置。互不影响。如果正在执行的方法是正儿八经的Java方法,那计数器就指着下一条指令,如果是 native 方法(非Java语言写的方法) 。计数器则为空。此外,这个内存区域是唯一一个不存在内存溢出的区域。
  2. 虚拟机栈:描述方法执行的内存模型,每个Java方法在执行的时候,会创造一个栈帧(一个方法对应一个栈帧)。这里要注意,如果方法中没有再调用子方法,那么这个虚拟机栈就只有一个栈帧。方法对应的栈帧里有局部变量表、操作数栈、动态链接、方法出口等。每个方法执行的开始就是入栈,结束就是出栈。
  3. 本地方法栈:和虚拟机栈类似,不同的是它执行的是非Java编写的方法。
  4. Java堆:Java堆有可能是运行时数据区域的最大一块区域。用来存放对象实例(这些对象实例都是类中创建或引用的实例,就好比是从main方法所在的哪个类中所创建的----> 运行时的数据区)。所以Java堆也是GC管理的主要区域(管理对象的回收)。
  5. 方法区(非堆,也经常称为永久代,持久区):注意区别于虚拟机栈,它管理的是整个类的逻辑。存放虚拟机加载的类的信息,常量、静态变量、jit编译后的代码等,是线程共享的。这个区域也会有GC,但是GC再这里的收益并不明显,而且此处执行GC条件苛刻。一般针对常量池的回收,或者类型的卸载回收。
  6. 运行时的常量池:方法区的一部分,用于存放所有被加载的Class文件中的常量池(系列号2)的 编译期的字面量和符号引用,并且这里的符号引用已经不是全类名的引用而是指针的物理引用。(字符串字面量存放于此,但是特意通过new String("abc")的字符串,先是在常量池中(如果没有"abc")建立"abc";再把常量池中的"abc"复制到堆里)运行时常量池相对于class文件常量池(系列号2)的另外一个特征是具有动态性,可以编译期产生,也可以在运行时产生。但是运行时常量位于方法区,也可能产生溢出。

对象的创建过程

虚拟机遇到 new 首先检查运行时的常量池中是否包含 创建类的符号引用,并且检查这个class是否已经被加载。接下来,虚拟机就开始为这个新生对象分配内存。因为对象所需的内存大小在类加载的时候就确定了。这时候如果 Java 堆内是规整的,就用指针碰撞的方法挪一个对象的空间出来使用。如果堆内存不规整,虚拟机就会维护一个列表,上面记录了空闲的空间,在列表上找一个大小合适的空间给新建的对象使用。这就是空闲列表的方式。

 

对象的在Java堆中的内存布局

  • 对象头
  • 实例数据
  • 对齐填充

对象是存放于Java堆的,其中对象头是一部分是存放对象的整体信息,比如对象的hash码,GC年龄代,线程锁等。另外一部分是对象指向对象所属类的类型指针。

实例数据就是存放对象实例的(包括父类的和子类的);

对其填充:Java堆中分配给对象的空间是8字节的倍数,没有达到就进行占位符填充。

 

访问堆中的对象方式

  • 句柄访问

在虚拟机栈的 reference 引用 句柄池中 对象实例的地址 和 对象类型数据;注意对象实例数据存放于Java堆,而对象类型数据存放于方法堆。

  • 直接指针访问

reference 存放对象的引用地址,在对象实例对象中 包含对象类型的指针。

总结:这两种方式各有优势,句柄方式:在对象移动(GC过程中经常发生)的时候只需要改变对象的引用,对象类型数据的引用无需改变。直接指针方式:定位速度快,在无需对象类信息时,节省了一次定位开销。使用较为频繁。

 

数据运行时各个数据区的溢出分析

待续...p57

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值