Java~学习在Java程序运行时JVM的多个数据区域具体是什么

运行时数据区域

  • JVM会在执行Java程序的过程中把它管理的内存划分为若干个不同的数据区域。这些数据区域各有各的用处,各有各的创建与销毁时间,有的区域随着JVM进程的启动而存在,有的区域则依赖用户线程的启动和结束而创建与销毁。

什么是线程私有和线程公有

  • 由于JVM的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现,因此在任何一个确定的时刻,一个处理器(多核处理器则指的是一个内核)都只会执行一条线程中的指令。因此为了切换线程后能恢复到正确的执行,每条线程都需要独立内存,各条线程之间互不影响,独立存储。我们就把类似这类区域称之为"线程私有"的内存
  • 反之就是线程公有内存

程序计数器(线程私有)

  • 程序计数器是一块比较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器。如果当前线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是一个Native方法,这个计数器值为空。

Java虚拟机栈(线程私有)

  • 虚拟机栈描述的是Java方法执行的内存模型 : 每个方法执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应一个栈帧在虚拟机栈中入栈和出栈的过程。声明周期与线程相同。
  • 局部变量表 : 存放了编译器可知的各种基本数据类型(8大基本数据类型)、对象引用。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在执行期间不会改变局部变量表大小。
  • 此区域一共会产生以下两种异常:
  1. 如果线程请求的栈深度大于虚拟机所允许的深度(-Xss设置栈容量),将会抛出StackOverFlowError异常。
  2. 虚拟机在动态扩展时无法申请到足够的内存,会抛出OOM(OutOfMemoryError)异常

本地方法栈(线程私有)

  • 地方法栈与虚拟机栈的作用完全一样,他俩的区别无非是本地方法栈为虚拟机使用的Native方法服务,而虚拟机栈为JVM执行的Java方法服务。

Java堆(线程共享)

  • Java堆(Java Heap)是JVM所管理的最大内存区域。Java堆是所有线程共享的一块区域,在JVM启动时创建。此内存区域存放的都是对象实例。JVM规范中说到:“所有的对象实例以及数组都要在堆上分配”。
  • Java堆是垃圾回收器管理的主要区域,因此很多时候可以称之为"GC堆"。根据JVM规范规定的内容,Java堆可以处于物理上不连续的内存空间中。Java堆在主流的虚拟机中都是可扩展的(-Xmx设置最大值,-Xms设置最小值)。
  • 如果在堆中没有足够的内存完成实例分配并且堆也无法再拓展时,将会抛出OOM
  • 注意: 每个进程都有自己的堆是有自己的堆的, 多个进程之间堆是不可共享的

方法区(线程共享)

  • 方法区与Java堆一样,是各个线程共享的内存区域。它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
  • JVM规范规定:当方法区无法满足内存分配需求时,将抛出OOM异常

运行时常量池(方法区的一部分)

运行时常量池是方法区的一部分,存放字面量与符号引用
字面量 : 字符串(JDK1.7后移动到堆中) 、final常量、基本数据类型的值。
符号引用 : 类和结构的完全限定名、字段的名称和描述符、方法的名称和描述符。

Java堆溢出

  • Java堆用于存储对象实例,只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免来GC清除这些对象,那么在对象数量达到最大堆容量后就会产生内存溢出异常。
  • Java堆内存的OOM异常是实际应用中最常见的内存溢出情况。当出现Java堆内存溢出时,异常堆栈信息"java.lang.OutOfMemoryError"会进一步提示"Java heap space"。当出现"Java heap space"则很明确的告知我们,OOM发生在堆上。

内存泄漏 : 泄漏对象无法被GC 内存溢出 :
内存对象确实还应该存活。此时要根据JVM堆参数与物理内存相比较检查是否还应该把JVM堆内存调大;或者检查对象的生命周期是否过长。

虚拟机栈和本地方法栈溢出

  • 由于我们HotSpot虚拟机将虚拟机栈与本地方法栈合二为一,因此对于HotSpot来说,栈容量只需要由-Xss参数来设置。
  • 如果是因为多线程导致的内存溢出问题,在不能减少线程数的情况下,只能减少最大堆和减少栈容量的方式来换取更多线程

关于虚拟机栈会产生的两种异常:
如果线程请求的栈深度大于虚拟机所允许的最大深度,会抛出StackOverFlow异常
如果虚拟机在拓展栈时无法申请到足够的内存空间,则会抛出OOM异常

如何理解基础数据类型和引用数据类型?

  • 基础数据类型变量中对应的内存空间 是之间保存了值 引用数据类型本质就是一个"低配指针" 它的引用是保存的一个地址 通过这个地址就可以找到new的对象本体
    在这里插入图片描述

如何理解 局部变量 成员变量 静态变量?

一定要清楚 局部变量在栈上 成员变量在堆上 静态变量在方法区
Java~基础知识 栈区 堆区 方法区 到底存了啥?
在这里插入图片描述

递归方法如何执行?

JVM中有个重要的区域 栈保存了方法之间的调用关系 每一层方法调用 都称为是一个栈帧 每一个栈帧就保存着自己的局部变量表 以及返回地址等信息

static方法和普通方法之间的区别是什么?

猜你喜欢

转载自blog.csdn.net/Shangxingya/article/details/107745806