Java的内存区域解析(新手向)

我们知道Java之所以可以跨平台是因为有了JVM虚拟机,将定义好标准格式的class文件加载到JVM中进行运行达到跨平台的效果.

为了更好的使用它,我们必须要对JVM虚拟机的内存分布进行了解,下面来看一看内存区域结构是怎么样的,具体作用又是什么.

1.Jvm的内存区域分布.

图片来源于百度百科:

从图片中我们可以看到,主要分为5大块:

1.程序计数器(PC):

  • 传统意义上的程序计数器:

CPU内部的寄存器中就包含一个程序计数器(x86下为eip寄存器,ARM下为R15寄存器),存放程序执行的下一条指令地址.

在程序开始执行前,将指令的起始地址送入PC,CPU按照PC的地址从内存中读取第一条指令.每一条指令执行时,CPU会自动修改PC的量至下一条指令的地址,承担程序指令的运输工作的就是PC了.

  • JVM的程序计数器:

JVM中不直接使用CPU中的PC进行操作,而是在内存中开辟一块空间来模拟CPU的程序计数器操作,值得注意的是JVM的PC所指向的并不是下一条命令的地址,而是正在执行的字节码地址.

线程:在JVM中PC是线程独享的,每一条线程有自己独立的PC用于存储正在执行的字节码地址.

2.虚拟机栈:

虚拟机栈描述的是java方法的内存执行模型,每个方法在执行的时候会建立一个栈帧,用于存放局部变量表,操作数栈,动态链接,方法出口等信息,每一个方法从调用直到执行完成的过程都对应着一个栈帧在虚拟机中入栈出栈的过程.

我们平时将内存分为堆和栈两块,其中所说的栈就是虚拟机栈中的局部变量表部分,局部变量表中存放了编译器可以知道的基本数据类型,对象引用,和返回后的所指向的字节码地址.

局部变量表会在编译期间完成内存分配,在进入一个方法的时候,其中分配的变量空间是早已经确定好的,如果递归层次过于深或者没有出口的情况下就会出现我们平时说的栈溢出(java.lang.StackOverflowError).

线程:在JVM中虚拟机栈是线程独享的,每一条线程有自己的栈空间.

3.本地方法栈:

在HotSpot虚拟机将本地方法栈和虚拟机栈合二为一,它们的区别在于,虚拟机栈为执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务.

线程:合二为一后,自然是私有的.

4.java方法区:

方法区也叫永久代,在逻辑上是堆中的一部分,用于存储每一个类的结构信息,例如:运行时常量池,字段和方法数据,构造函数和普通方法的字节码内容,到了Java 8,永久代被彻底地移出了JVM,取而代之的是元空间.

线程:方法区中的数据是线程共享的.

5.java堆:

堆是JAVA中我们可利用的最大的一块内存区域,几乎所有的对象实例和数组实例都要在Java堆上分配,同时,Java 堆也是发生GC收集的主要区域.

线程:堆上的数据不用说,自然是线程共享的.

2.总结

我们平时主要使用的是虚拟机栈与堆,虚拟机栈是线程独享(私有的),堆为线程共享的.

局部变量表:
局部变量表是一组存储变量值的存储空间,用于存放方法参数和方法内部定义的局部变量.

操作数栈:
操作数栈是被组织成一个以字长为单位的数组,通过标准的栈操作—压栈和出栈—来访问.

对象引用:

People p;//声明了一个People类型变量名称叫p的变量
p= new People("111","222");//在堆上面为People对象新开辟一段空间.让p指向其地址,这就是一个对象引用.

符号引用与直接引用:

在解析阶段,Java虚拟机会把类的二级制数据中的符号引用替换为直接引用。

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

比如org.simple.People类引用了org.simple.Language类,在编译时People类并不知道Language类的实际内存地址,因此只能使用符号org.simple.Language(假设是这个,当然实际中是由类似于CONSTANT_Class_info的常量来表示的)来表示Language类的地址。

直接引用:

直接引用是和虚拟机的布局相关的,同一个符号引用在不同的虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用,那引用的目标必定已经被加载入内存中了。

(1)直接指向目标的指针(比如,指向“类型”【Class对象】、类变量、类方法的直接引用可能是指向方法区的指针)

(2)相对偏移量(比如,指向实例变量、实例方法的直接引用都是偏移量)

(3)一个能间接定位到目标的句柄

参考资料:

1.https://www.cnblogs.com/shinubi/articles/6116993.html

2.http://www.codeceo.com/article/jvm-memory-stack.html

3.http://www.sczyh30.com/posts/Java/jvm-memory/

个人参考了资料进行总结,如果有不对或者不足之处欢迎指正.

posted @ 2018-04-29 22:17  CurryRice  阅读(81)  评论(0)    收藏  举报