白小姐和JVM第一次:JVM的线程私有区域和线程共享区域

文章目录

    • 1、JVM简介
      • 1.1虚拟机简介:
      • 1.2JVM和其他两个虚拟机的区别:
    • 2、Java内存区域与内存溢出异常
      • 2.1运行时数据区域:
      • 2.2线程私有区域
        • 2.2.1 程序计数器
          • 什么是线程私有?
        • 2.2.2Java虚拟机栈
          • **局部变量表:**
        • 2.2.3本地方法栈
      • 2.3线程共享区域
        • 2.3.1Java堆
        • 2.3.2方法区
        • 2.3.3运行时常量池(方法区的一部分)
    • 总结

1、JVM简介

1.1虚拟机简介:

JVM(Java Virtual Machine的简介,意为Java虚拟机)
虚拟机:指通过软件模拟的具有完整硬件功能的,运行在一个完全隔离的环境中的完整计算机系统,常见虚拟机有: JVM、VMwave、Virtual Box

1.2JVM和其他两个虚拟机的区别:

a、VMware与VirtualBox是通过软件模拟物理CPU的指令集,物理系统中会有很多的寄存器
b、JVM则是通过软件模拟Java字节码的指令集,JVM中只是主要保留了PC寄存器,其他的寄存器都进行了裁剪JVM是一台被定制过的现实中不存在的计算机。
我们只需要知道:Java是一台被裁剪过的,只能处理Java字节码的虚拟机。

2、Java内存区域与内存溢出异常

2.1运行时数据区域:

JVM会在执行Java程序的过程中把它管理的内存划分为若干个不同的数据区域,这些数据区域各有各的用处,各有各的创建与销毁时间,有的区域随着JVM进程的启动而存在,有的区域则依赖于用户线程的启动和结束而创建与销毁,一般来说:JVM管理的内存将会包含以下几个运行时的数据区域:
线程私有区域:程序计数器、Java虚拟机栈、本地方法栈
线程共享区域:Java堆、方法区、运行时常量池

2.2线程私有区域

2.2.1 程序计数器

 程序计数器是一块比较小的内存空间,可以看作是当前线程锁执行的字节码的行号指示器。
 如果当前线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是一个Native方法,这个计数器值为空。
 程序计数器内存区域是唯一一个在JVM规范中没有规定任何 OOM情况的区域。
这个我们也十分容易理解,我们的程序计数器只是存储正在执行的虚拟机字节码的指令的地址,是一个定长的数据,所以它不会存在内存溢出的情况。所以我们不需要为他规定任何OOM情况。

什么是线程私有?

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

2.2.2Java虚拟机栈

 虚拟机栈描述的是Java方法执行的内存模型:每个方法执行的同时都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法调用至执行完成的过程,就对应一个栈帧在虚拟机栈中入栈和出栈的过程。声明周期与线程相同。
我们在Java中学习的栈区实际上就是此处我们的虚拟机栈,详细一点就是我们的虚拟机栈中的局部变量表的部分。

局部变量表:

 存放了编译器可知的各种基本数据类型(8大基本数据类型)、对象引用。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法的时候,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,在执行期间不会改变局部变量表的大小。
此区域一共会产生以下两种异常:
栈溢出:1、如果线程请求的栈深度大于虚拟机所允许的深度(-Xss设置栈容量),将会排除StackOverFlowError异常。
内存溢出:2、虚拟机在动态扩展时无法申请到足够的内存,会抛出OOM异常。

2.2.3本地方法栈

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

2.3线程共享区域

2.3.1Java堆

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

2.3.2方法区

 方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。在JDK8以前的HotSpot虚拟机中,方法区也被成为“永久代”(在JDK8之后被称为元空间)
 永久代并不意味着数据进入方法区就永久存在,此区域的内存回收主要是针对常量池的回收以及对类型的卸载。
比如:我们如果通过反射,把我们的一个文件加载到我们的永久代里面,卸载就不会存在,还有就是对于不常用的变量进行回收。
我们要时刻记住的是,能加载就能够卸载,所以我们的永久代里面的数据也不会是我们所说的永远存在。
JVM规范规定:当方法区无法满足内存分配需求时,将会抛出OOM异常。

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

运行时长量池是方法区的一部分,存放字面量与符号引用
字面量:字符串(jdk7以后将其放在了堆空间上)、final常量、基本数据类型的值。
符号引用:类和结构的完全限定名,字段的名称和描述符,方法的名称和描述符。

总结

这是JVM虚拟机的最基础的知识,也是为我们了解Java中的存储机制打下的基础。所以,宝宝要好好理解。

你可能感兴趣的:(专业,概念)