java虚拟机(一)java虚拟机的运行时内存划分及对象创建过程

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,java虚拟机运行时数据区包括:方法区、虚拟机栈、本地方法区、堆、程序计数器,如下图所示:

程序计数器

程序计数器的作用可以看成是当前线程所执行的字节码行号指示器。字节码解释器工作时就是通过改变计数器的值来选择下一条需要执行的字节码的指令。java虚拟机的多线程是通过线程轮流切换来分配处理器执行时间的方式实现的,为了线程切换之后能恢复到正确的执行位置,每个线程就需要一个独立的程序计数器。

java虚拟机栈:

java虚拟机栈线程私有,每个方法被执行的同时都会创建一个栈帧用于存放局部变量表、操作栈、动态链接、方法出口等信息。

局部变量表存放了编译器可知的八个基本数据类型对象引用、和returnAddress类型(指向了一条字节码指令的地址),局部变量表所需的内存空间再编译期间完成分配。

java虚拟机栈可能会出现两种异常;第一种如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出StackOverFlow异常;第二种如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常

本地方法栈:

扫描二维码关注公众号,回复: 8503192 查看本文章

本地方法栈的功能和虚拟机栈类似,本地方法栈为虚拟机用到的Native方法服务,一个Native Method就是一个java调用非java代码的接口,本地方法栈也会抛出StackOverFlowOutOfMemoryError异常

java堆

java堆可以说是java虚拟机中所管理的内存最大的一块,java堆被所有线程共享,虚拟机启动的时候创建。java堆中存放对象实例的数组。几乎所有的对象实例以及数组都在堆上分配,java堆也是垃圾回收器管理的主要区域,java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,这和磁盘空间很相似。当一个堆无法再扩展时,会抛出OutOfMemoryError异常。

方法区

方法区也是线程共享的内存区域,用于存放已经被虚拟机加载的类信息常量静态变量即时编译器编译后的代码等数据,java虚拟机对方法区的限制十分宽松,和java堆一样不需要连续的内存外,还可以选择不实现垃圾回收,因此还有人把方法区称为“永生代”,这个区域的内存回收主要是针对常量池的回收对类型的卸载,当方法区无法满足内存分配需求时,会抛出OutOfMemoryError异常。

运行时常量池也是方法区的一部分,Java语言并不要求常量一定只能在编译期产生,运行期间也可能产生新的常量,这些常量被放在运行时常量池中。类加载后,常量池中的数据会在运行时常量池中存放!这里所说的常量包括:基本类型包装类(包装类不管理浮点型,整形只会管理-128到127)和String(也可以通过String.intern()方法可以强制将String放入常量池)

java对象的访问

在java中随处可以见到对象的访问,但是如果没有学习过java虚拟机,就无法深入理解对象的创建过程究竟是怎样的,当创建一个对象时:

Object obj = new Object()

Object obj会反映到java虚拟机栈的变量表中,作为一个引用类型数据出现,“new Object()”会反映到java堆中,在java堆上创建一个Object类型的实例数据值的结构化内存,这块内存的长度是不固定的。在java堆中还存放了了能查到此对象类型数据(对象类型、父类、接口、方法等)的地址信息,

这些信息存放在方法区中。

如何访问到方法区中的对象类型数据,也有两种不同的方法:句柄直接指针,访问方式如下所示:

两种方法各有好坏,现在主要的java虚拟机均采用第二种方法。

发布了54 篇原创文章 · 获赞 604 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_41973594/article/details/101119453