JVM内存结构

JAVA内存区域

JVM在执行Java程序的过程中会把它管理的内存划分为若干个不同的数据区域,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区等。前三者为线程私有的,后两者为线程共享区域。

深入理解Java虚拟机(第二版)P39

1. 程序计数器(Program Counter Register)

程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码行号指示器。
因为JVM的多线程是通过线程轮换并分配处理器执行时间来实现的,所以在任意时刻,一个处理器都只会执行一条线程中的指令。所以为了切换后能够恢复到正确的执行位置,每条线程都需要一个独立的计数器,它们互不影响。因此,程序计数器是线程私有的。
如果线程执行的是一个Java方法,计数器记录正在执行的虚拟机字节码指令的地址。如果是Native方法,能为空。

2. Java虚拟机栈(Java Virtual Machine Stacks)

Java虚拟机栈描述的是Java方法执行的内存模型: 每个方法执行的时候会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。一个方法从执行到返回,就对应一个栈帧在虚拟机栈中入栈和出栈的过程。

局部变量表

局部变量表存放的是编译期可知的各种基本数据类型、对象引用(reference类型)、returnAddress类型。其中64位长度的long和double类型数据会占用2个局部变量空间(Slot),其余只占用1个。局部变量表所需空间在变异期间完成分配,所以当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间完全确定,运行期间不会改变。

3. 本地方法栈(Native Method Stack)

本地方法栈和虚拟机栈的作用非常相似、区别在于一个执行的是Java方法,一个执行的是Native方法。
使用native关键字表示的方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由Java去调用。

4. Java堆(Java Heap)

Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。这个内存区域的唯一目的就是存放对象实例以及数组。Java堆是垃圾收集器的主要区域。从内存回收的角度来看,现代收集器都是使用分代收集算法,所以可以细分为:新生代和老年代,新生代还可以分为Eden空间、From Survivor空间、To Survivor空间等。
Java堆的JVM参数主要是 -Xms和-Xmn。

5. 方法区(Method Area)

方法区和Java堆一样,是各个线程共享的内存区域,它被用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译期编译后的代码等数据

运行时常量池(Runtime Constant Pool)

运行时常量池是方法区的一部分。 Class文件中除了类的版本、字段、方法、接口等描述信息,还有常量池(Constant Pool Table),主要包括编译期生成的各种字面量(Literal)和符号引用量(Symbolic References)。字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等,符号引用则属于编译原理方面的概念,符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可。包括了如下三种类型的常量:

  • 类和接口的全限定名
  • 字段名称和描述符
  • 方法名称和描述符
    这部分内容在类加载后进入方法区的运行时常量池存放。
    运行时常量池相对于CLass文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有编译期才能产生,也就是并非预置入CLass文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用比较多的就是String类的intern()方法。
    常量池的好处
    常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。
    例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。
  • 节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
  • 节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用是否相等,也就可以判断实际值是否相等。
    双等号==的含义
  • 基本数据类型之间应用双等号,比较的是他们的数值。
  • 复合数据类型(类)之间应用双等号,比较的是他们在内存中的存放地址。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 索引:堆、栈、方法区、直接内存、堆和栈区别 所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢...
    逢栲怭過阅读 2,934评论 0 0
  • 在Java虚拟机规范中将Java运行时数据划分为6种,分别为: PC寄存器(程序计数器) Java栈 堆 方法区 ...
    马小跑_7933阅读 1,872评论 0 0
  • JVM(Java Virtual Machine Java 虚拟机)是一种用于计算设备的规范,基于这套规范,许多团...
    大佛爱读书阅读 3,325评论 0 0
  • 引言: 昨天的重要级分析出来后,今天的效率明显提升了,老婆>一建>工作,以目的导向来经营自己的生活,不要为了别人的...
    mei_a827阅读 1,488评论 0 0
  • 夏夜七点钟暗蓝的天空。我微微扬起嘴角。我想我已经看淡,不再去簇拥着喧闹,在自己的一方天空安静地沉沦。 窗外仍看...
    晴天无妨阅读 2,738评论 0 0