JVM- 运行时数据区

2021/4/28 10:56:07

本文主要是介绍JVM- 运行时数据区,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

  • 内存
  • 运行时数据区
    • 运行时环境
    • 程序计数寄存器
      • 作用
      • PC寄存器介绍
      • CPU时间片
      • PC寄存器设定为线程私有的原因
      • 使用PC寄存器存储字节码指令地址作用
      • 背景
      • Java虚拟机栈
      • 生命周期
      • 作用
      • 优点
      • 缺点
      • 相关问题
    • 栈的详细介绍
    • 引申--本地方法
      • 说明
      • 现状
      • 为什么要使用Native Method?
        • 与Java环境外交互
        • 与操作系统交互
        • Sun’s Java
    • 本地方法栈

内存

内存是非常重要的系统资源,是硬盘和CPU的中间仓库和桥梁,承载着操作系统和应用程序的实时运行。JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策略,保证了JVM的高效稳定运行。不同的JVM对于内存的划分方式和管理机制存在着部分差异。结合JVM虚拟机规范,探讨经典的JVM内存布局。

运行时数据区

运行时数据区

运行时环境

运行时环境

后台系统线程举例

程序计数寄存器

JVM中的程序计数寄存器(Program Counter Register)中,Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能运行。
这里,并非是广义所指的物理寄存器,或许将其翻译为PC计数器(或指令计数器)会更贴切(也称为程序钩子)。JVM中的PC寄存器是对物理寄存器的一种抽象模拟。
  • 它是一块很小的内存空间,几乎可以忽略不计。也是运行速度最快的存储区域。
  • 在JVM规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期一致。
  • 任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的Java方法的JVM指令地址;或者,如果是在执行native方法,则是为指定值(undefend)。

程序计数器

作用

PC寄存器用来存储指向下一条指令的地址,即将要执行的指令代码。由执行引擎读取下一条指令。

PC寄存器介绍

  • 它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
  • 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
  • 它是唯一一个在Java虚拟机规范中没有规定任何OutOtMemoryError情况的区域。

CPU时间片

  • CPU时间片即CPU分配给各个程序的时间,每个线程被分配一个时间段,称它为他的时间片。
  • 在宏观上:我们可以同时打开多个应用程序,每个程序并行不悖,同时运行。
    在微观上:由于只有一个CPU,一次只能处理程序要求的一部分,如何处理公平,一种方法就是引入时间片,每个程序轮流执行。
    PC寄存器

PC寄存器设定为线程私有的原因

  • 我们都知道,所谓的多线程是在一个特定的时间段内,只会执行其中某一个线程的方法,CPU会不停地做任务切换,这样必然导致经常中断或恢复,为了保证分毫无差,且能明确地记录各个线程正在执行的当前字节码指令地址,最好的办法自然是为每一个线程都分配一个PC寄存器,这样,各个线程之间便可以进行独立计算,从而不会出现互相干扰的情况。
  • 由于CPU时间片轮限制,众多线程在并发执行过程中,任何一个确定的时刻,一个处理器或者多核处理器中的一个内核,只会执行某个线程中的一条指令。

使用PC寄存器存储字节码指令地址作用

  • 因为CPU需要不停的切换各个线程,这时候切换回来以后,就得知道接着从哪开始继续执行。
  • JVM的字节码解释器就需要通过改变PC寄存器的值来明确下一条应该执行什么样的字节码指令。PC寄存器

背景

由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器。

Java虚拟机栈

Java虚拟机栈 Java Virtual Machine Stack,早期也叫Java栈。每个线程创建时都会创建一个虚拟机栈,其内部保存一个个栈帧 Stack Frame,对应着一次次的Java方法的调用
• 线程是私有的。

生命周期

生命周期和线程一致

作用

主管Java程序运行,它保存方法的局部变量、部分结果,并参与方法的调用和返回。
• 局部变量VS 成员变量(或属性)
• 基本数据变量VS 引用类型变量(类、接口、数组)

优点

• 跨平台,指令集小,编译器容易实现

缺点

• 性能下降,实现同样的功能需要更多的指令

相关问题

有不少Java开发人员一提到JAVA内存结构,就会非常粗粒度的将JVM中的数据区理解为仅有JAVA堆(Heap)和JAVA栈(Stack)?why?

  • 栈是运行时的单位
  • 堆是存储的单位
  • 栈是解决程序的运行问题,即程序如何执行或如何处理数据。
  • 堆解决的是数据存储的问题,即数据怎么放,放哪儿

栈

栈的详细介绍

点击进入详细链接

引申–本地方法

  • 简单地讲,一个Native Method就是一个Java调用非Java代码的接口。
    • 一个Native Method是这样的一个Java方法:该方法的实现由非Java语言实现,比如C。这个特征并非Java所特有买很多其他的编程语言都有这一个机制,比如C++中,就可以用extern “C”告知C++编译器去调用一个C的函数。
    • A native method is a Java method whose implementation is provided by non-Java code.
  • 在定义一个native method时,并不提供实现体(有些像定义一个Java interface),因为其实现体是由非Java语言在外面实现的。
  • 本地接口的作用是融合不同的编程语言为Java所用,他的初衷是融合C/C++程序。

说明

标识符native可以与所有其他的Java标识符连用,但是abstract除外。

现状

目前该方法使用的越来越少,除非是与硬件有关的应用,比如通过Java程序驱动打印机或Java系统管理生产设备,在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用Socket通信,也可以使用Web Service等等。
本地方法-库

为什么要使用Native Method?

Java使用起来非常方便,然后有些层次的任务用Java实现起来不容易,或者说对程序的效率很在意时,问题就来了。

与Java环境外交互

有时Java应用需要与Java外面的环境交互,这是本地方法存在的主要原因。
Java需要与一些底层下同交互,如操作系统或某些硬件交换信息时的情况。本地方法正是这样一种交流机制:它为我们提供了一个非常简洁的接口,而且我们无需去了解Java应用之外的繁琐细节。

与操作系统交互

JVM支持着Java语言本身和运行时库,它是Java程序赖以生存的平台,它由一个解释器(解释字节码)和一些连接到本地代码的库组成。然而不管怎样,它毕竟不是一个完整的系统,它经常依赖于一些底层系统的支持。这些底层系统常常是强大的操作系统。通过使用本地方法,我们得以用Java实现了jre的与底层系统的交互,甚至JVM的一些部分就是C写的。还有,如果我们要使用一些Java语言本身没有提供封装的操作系统的特性时,我们也需要使用本地方法。

Sun’s Java

Sun的解释器是用C实现的,这使的它能像一些普通的C一样与外部交互。
jre大部分是用Java实现的,它也通过一些本地方法与外界交互。例如:类java.long.Thread的setPrioroty()方法是用Java实现的,但是它实现调用的是该类里的本地方法setPrioroty0()。这个本地方法是用C实现的,并被植入JVM内部,在Windows 95的平台上,这个本地方法最终将调用Win32 setPrioroty() API。这是一个本地方法的具体实现由JVM直接提供,更多的情况是本地方法由外部的动态链接库external dynamic link library提供,然后被JVM调用。本地方法-库

本地方法栈

本地方法栈 Native Method Stack

Java虚拟机栈用于管理Java方法的调用,而本地方法栈用于管理本地方法的调用。

  • 本地方法栈,也是线程私有的。
  • 允许被实现成固定或可动态扩展的内存大小(在内存溢出方面是相同的)。
  • 如果线程请求分配的栈容量超过本地方法栈允许的最大容量,Java虚拟机将会抛出一个StackOverflowError异常。
  • 如果本地方法栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的本地方法栈,那么Java虚拟机将会抛出一个OutOfMemoryError异常。
  • 本地方法是使用C语言实现的。
  • 它的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载本地方法库。
  • 当某个线程调用一个本地方法时,他就进入了一个全新的并且不再受虚拟机限制的时间。他和虚拟机拥有同样的权限。
  • 本地方法可以通过本地方法接口来访问虚拟机内部的运行时数据区。
    - 它甚至可以直接使用本地处理器中的寄存器。
    - 直接从本地内存的堆中分配任意数量的内存。
  • 并不是所有的JVM都支持本地方法。因为Java虚拟机规范并没有明确要求本地方法栈的使用语言、具体实现方式、数据结构等。如果JVM产品不打算支持native方法,也可以无需实现本地方法栈。
  • 在Hotspot JVM中,直接将本地方法栈和虚拟机栈合二为一。
    本地方法栈
    本地方法栈

堆



这篇关于JVM- 运行时数据区的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程