深入理解java虚拟机(一)java的内存区域

123

程序计数器可以看作当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条 需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来实现。每一个线程都有一个独立的程序计数器,各个线程之间的计数器互不影响,独立存储,我们把这类内存区域称为“线程私有”的内存。

java虚拟机栈:与程序计数器一样,也是线程私有的,生命周期与线程相同。虚拟机栈描述的是java方法执行的内存模型。栈中存储的是一个个栈帧,每个栈帧对应一个被调用的方法,栈帧之中存储着局部变量表、操作数栈、动态链表、方法出口等。调用一个方法,即对应一个栈帧入栈,方法调用完成,则该方法对应的栈帧出栈。

局部变量表存放着各种基本数据类型、对象、引用等。

操作数栈,想必学过数据结构中的栈的朋友想必对表达式求值问题不会陌生,栈最典型的一个应用就是用来对表达式求值。想想一个线程执行方法的过程中,实际上就是不断执行语句的过程,而归根到底就是进行计算的过程。因此可以这么说,程序中的所有计算过程都是在借助于操作数栈来完成的。

指向运行时常量池的引用,因为在方法执行的过程中有可能需要用到类中的常量,所以必须要有一个引用指向运行时常量。

方法返回地址,当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址。

由于每个线程正在执行的方法可能不同,因此每个线程都会有一个自己的Java栈,互不干扰。

java堆:java堆是java虚拟机管理的内存中最大的一块,是被所有线程共享的一块内存区域,在虚拟机启动时创建。该内存区域唯一的 目的就是存放对象实例。所有的对象实例以及数组都要在堆上分配。java堆是垃圾收集管理的主要区域,所以也被叫做GC堆。java可以分为新生代和老年代。java堆可以处于物理不连续的内存空间中。

方法区:用来存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。这里可以看到常量也会在方法区中,是因为方法区中有一个运行时常量池,为什么叫运行时常量池,因为在编译后期生成的是各种字面量(字面量的意思就是值,比如int i=3,这个3就是字面量的意思)和符号引用,这些是存放在一个叫做常量池(这个常量池是在字节码文件中)的地方,当类加载进入方法区时,就会把该常量池中的内容放入运行时常量池中。

对象的创建:

创建对象,在堆中开辟内存时是如何分配内存的?

       两种方式:指针碰撞和空闲列表。我们具体使用的哪一种,就要看我们虚拟机中使用的是什么了。

       指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存度放一边,空闲的内存放另一边,中间放着一个指针作为分界点的指示器,所分配内存就仅仅是把哪个指针向空闲空间那边挪动一段与对象大小相等的举例,这种分配方案就叫指针碰撞

       空闲列表:有一个列表,其中记录中哪些内存块有用,在分配的时候从列表中找到一块足够大的空间划分给对象实例,然后更新列表中的记录。这就叫做空闲列表

参考博客:https://www.cnblogs.com/whgk/p/6138522.html

猜你喜欢

转载自blog.csdn.net/weixin_42173193/article/details/84674332