JVM运行时数据区域

概述

Java将内存控制的权力交给Java虚拟机,它自动帮我们分配内存和释放内存。不像C、C++开发语言,需要程序员为每个new对象去写配对的delete/free代码。一旦JVM中出现了内存泄漏和内存溢出,如果不了解JVM如何使用内存,那么对排查错误将是一项异常艰难的工作。同时无限制或者不合理的new一些对象,会出现一些内存抖动,因而影响体验和性能。因此了解JVM的内存分配机制,有助于写出高性能的程序。

JVM运行时数据区域

JVM在执行Java程序过程中,把它所管理的内存划分为不同的数据区域,这些区域有各种的用途,以及创建和销毁时间。

一、线程隔离数据区域

1.1 程序计数器

看做当前线程所执行的字节码行号指示器。

1.2 虚拟机栈

描述Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储 局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用到执行完成的过程,对应栈帧在虚拟机中入栈到出栈的过程。

局部变量表存放编译期可预知的基本数据类型,对象引用和returnAddress。局部变量表所需要的内存空间在编译期间完成分配,当进入一个方法是,这个方法需要在帧中分配多大的局部变量空间是确定的,在方法运行期间不会改变。这里不会改变的原因是因为:基本类型比较容易理解,大小固定;对象在这里存储的是对象的引用指针,或者对象的句柄,可以理解为内存地址,因此大小可以确定。

1.3 本地方法栈

与虚拟机栈类似,为虚拟机使用到的Native方法服务。

二、线程共享区域

2.1 Java堆(Java Heap)

虚拟机启动时创建,存放对象实例,几乎所有对象实例都在这里分配;同时也是GC 管理的主要区域,根据分代收集算法,堆可以分为新生代和老年代;再细致一点,可以分为Eden空间、From Survivor空间、To Survivor空间。

2.2 方法区

存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

2.2.1 运行时常量池

存储Class在编译期生成的各种字面量和符号引用。

字面量: 固定值表示法,比较接近Java语言层面的常量概念,如文本字符串、生命为final的常量值等。

符号引用: 符号引用以一组符号来描述所引用的目标。符号引用可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可;

属于编译原理方面的概念,包括如下三类常量:

  1. 类和接口的全限定名
  2. 字段的名称和描述符
  3. 方法的名称和描述符

Java代码在进行javac编译的时候,没有连接这一步骤,而是在虚拟机加载Class文件的时候进行动态连接。也就是说,在Class中间中不糊保存各个字段、方法的最终内存布局信息,因此这些字段,方法的符号引用不经过运行期转换的话无法得到真正的内存入口地址,也就无法直接被虚拟机使用。当虚拟机运行时,需要重常量池获得对应的符号引用,再在类创建或者运行时解析、翻译到具体的内存地址之中。

int a = 1; //1为字面量
String hello = "Hello World"; //Hello World 为字面量; hello 为符号引用

参考资料:深入理解java虚拟机-周志明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值