首页 技术 正文
技术 2022年11月16日
0 收藏 332 点赞 3,020 浏览 2594 个字

java虚拟机学习笔记

Java技术的核心就是Java虚拟机,因为所有的Java程序都在虚拟机上运行。Java程序的运行需要Java虚拟机、Java API和Java Class文件的配合。Java虚拟机实例负责运行一个Java程序。当启动一个Java程序时,一个虚拟机实例就诞生了。当程序结束,这个虚拟机实例也就消亡。

  java虚拟机结构图如下:

                     java虚拟机笔记-1


1、Java运行时数据区域

当类加载器将class文件加载到jvm后,Java虚拟机在执行java程序的过程中会把它管理的内存划分为若干个不同的数据区,java虚拟机所管理的内存将会包含以下几个运行时数据区域:

  1. 程序计数器(Program Counter Register)
  2. java虚拟机栈(Java Virtual Macchine Stacks)
  3. 本地方法栈(Native Method Stack)
  4. java堆(Java Heap)
  5. 方法区(Method Area)
  6. 运行时常量池(Runtime Constant Pool)

  1-1、程序计数器:

  程序计数器是一块较小的内存,可以被认作时当前线程所执行的字节码的行号指示器。字节码解释器通过改变计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器实现。每个线程都需要一个独立的计数器,所有程序计数器不是线程共享的。

  当线程执行的是java方法时,计数器记录当前正在执行的虚拟机字节码指令的地址,如果执行的是本地方法,则计数器值为空(Undefined),此内存也是唯一一个在虚拟机规范中没有规定任何OutOfMemoryError情况的区域。  

  1-2、java虚拟机栈:

  该区域也是线程私有的,它的生命周期与线程相同。每个方法在执行时都会创建一个帧栈用于存储局部变量表、操作数栈、动态链接、方法出口信息等,该区域规定了两种异常状况:StackOverflowError和OutOfMemoryError

  每个方法从调用到执行完成的过程都会有一个人对应的帧栈在虚拟机栈中入栈出栈。栈由许多栈帧组成,一个栈帧包含一个Java方法调用的状态。当线程调用一个Java方法时,虚拟机压入一个新的栈帧到该线程的栈中,当该方法返回时,这个栈帧就从栈中弹出。Java栈存储线程中Java方法调用的状态–包括局部变量、参数、返回值以及运算的中间结果等。Java虚拟机没有寄存器,其指令集使用Java栈来存储中间数据。这样设计的原因是为了保持Java虚拟机的指令集尽量紧凑,同时也便于Java虚拟机在只有很少通用寄存器的平台上实现。另外,基于栈的体系结构,也有助于运行时某些虚拟机实现的动态编译器和即时编译器的代码优化。

  1-2-1、局部变量区

  局部变量区被组织为以字长为单位、从0开始计数的数组。字节码指令通过从0开始的索引使用其中的数据。类型为int, float, reference和returnAddress的值在数组中占据一项,而类型为byte, short和char的值在存入数组前都被转换为int值,也占据一项。但类型为long和double的值在数组中却占据连续的两项。

  1-2-2、操作数栈

  和局部变量区一样,操作数栈也是被组织成一个以字长为单位的数组。它通过标准的栈操作访问–压栈和出栈。由于程序计数器无法被程序指令直接访问,Java虚拟机的指令是从操作数栈中取得操作数,所以它的运行方式是基于栈而不是基于寄存器。虚拟机把操作数栈作为它的工作区,因为大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。

  1-2-3、帧数据区

  除了局部变量区和操作数栈,栈帧还需要帧数据区来支持常量池解析、正常方法返回以及异常派发机制。每当虚拟机要执行某个需要用到常量池数据的指令时,它会通过帧数据区中指向常量池的指针来访问它。除了常量池的解析外,帧数据区还要帮助虚拟机处理Java方法的正常结束或异常中止。如果通过return正常结束,虚拟机必须恢复发起调用的方法的栈帧,包括设置程序计数器指向发起调用方法的下一个指令;如果方法有返回值,虚拟机需要将它压入到发起调用的方法的操作数栈。为了处理Java方法执行期间的异常退出情况,帧数据区还保存一个对此方法异常表的引用。

  1-3、本地方法栈

  本地方法栈与虚拟机栈的作用是相似的,区别仅仅是虚拟机栈为虚拟机执行Java方法,而本地方法栈执行虚拟机使用到的Native方法。

  1-4,、java堆

  Java堆一般是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的,是非线程安全的,在虚拟机启动时创建。

此区域的唯一目的是存放对象实例,几乎所有对象实例和数组(数组实质也是对象)都是在这里分配内存(Java虚拟机规范的原文:The heap is the runtime data area from which memory for all class instance and arrays is allocated.)但是随着虚拟机相关技术的发展,栈上分配等技术将会导致所有对象分配在堆上也不再是那么“绝对”了。  

  因为几乎所有对象都分配在Java堆上,所以Java堆也是垃圾收集器管理的主要区域。从内存角度看,由于现在垃圾收集器基本采用分算法,所欲Java堆又可以细分为:新生代(young area)和老年代(old area),(java8后移除永久代);再细致一点又可以分为Eden、From Survivor 、To Survivor。

  VisualVM的(JAVA8)Visual GC视图如下:

java虚拟机笔记-1

 可以看到Java堆首先被分为新生代和老年代两块区域,新生代又细分为eden、s0、s1三块区域,如此划分应是为了提高虚拟机效率。

  1-5、方法区

  方法区与Java堆一样,也是线程共享的,它被用来存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据。java虚拟机对方法区的限制非常宽松,除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。

 

  1-6、运行时常量池

  运行时常量池是 方法区 的一部分,用于存放编译期间生成的各种字面量和符号引用,这部分内容是在类加载后进入方法区运行时常量池中存放。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,918
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,444
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,255
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,069
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,701
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,741