深入Java虚拟机读书笔记[5]

简介:

第五章 Java虚拟机

1. Java虚拟机内部体系结构

2013-10-08-inside-the-java-virtual-machine-05

在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

2. 数据类型

Java虚拟机中的数据类型分为基本类型和引用类型。Java语言中的所有基本类型同样为Java虚拟机中的基本类型。Java虚拟机把boolean看作基本类型,但是指令集对boolean的支持十分有限。编译为字节码的时候使用int或byte表示boolean。boolean数组当作byte数组使用,但是在堆区也可能被表示为位域。

2013-10-08-inside-the-java-virtual-machine-05

3. 类装载子系统

顺序:装在、连接、初始化

Java虚拟机中有两种类装载器:启动类装载器和用户自定义类装载器。前者是Java虚拟机实现的一部分,后者则是Java程序的一部分。后者通往虚拟机的通道有defineClass、findSystemClass、resolveClass。

4. 方法区

方法去存储关于被装载类型的信息。所有线程共享方法区,因此必须设计为线程安全的。方法区不必固定大小, 不必连续,可以在一个堆中自由分配,允许指定初始大小以及最小最大尺寸。存储的信息包括: a) 全限定名 b) 直接超类全限定名 c) 类还是接口 d) 访问修饰符 e) 直接超接口全限定名的有序列表 f) 该类型常量池 g) 字段信息 h) 方法信息 i) 除了常量外所有类变量(静态) j) 一个到ClassLoader的引用 k) 一个到Class的引用

5. 堆

运行时创建的所有类实例和数组放在同一个堆中。一个Java虚拟机实例中只有一个堆空间,所有线程共享。堆区也不必连续,可以动态扩展或者收缩。对象的内部表示有虚拟机实现者决定。

数组页拥有一个与他们的类相关联的Class实例,具有相同维度和类型的数组都是同一个类的实例。

6. 程序计数器

运行中的Java程序每一个线程都有自己的PC。大小是一个字长,可以持有一个指针,也能持有一个returnAddress。 当线程执行某个Java方法时,PC寄存器的内容总是下一条将被执行指令的“地址”,可以是一个本地指针也可以是在方法字节码中相对该方法起始地址的偏移量。如果正在执行本地方法,则值为“undefined”。

7. Java栈

每当启动一个新线程的时候,Java虚拟机都会为他分配一个Java栈。Java以帧为单位保存线程的运行状态,虚拟机只会以帧为单位压栈或者出栈。正在执行的方法称为该线程的当前方法,当前方法使用的栈帧称为当前帧,当前方法所属的类称为当前类,当前类常量池称为当前常量池。当虚拟机遇到栈内操作指令的时候,对当前帧内数据执行操作。

Java方法可以以两种方式完成:通过return返回;抛出异常中智。不管哪种方式,虚拟机都会弹出当前Java栈然后释放。栈上的所有数据都是此线程私有的。

Java栈在内存中也不必连续,可以分布在连续的栈里,也可以分布在堆里,或者两者兼而有之 。

8. 栈帧

栈帧由三部分组成:局部变量区,操作数栈和帧数据栈。

局部变量区 被组织为一个以字长为单位、从0开始计数的数组。字节码通过从0开始的所以来使用其中的数据。类型为int,float,reference和returnAddress的值在数组中只占一项。类型为byte,short和char值在存入数组前都将被转换为int值,在栈中都当作int处理,只有存回堆或者方法区时才转换为原来的类型。long和double的值在数组中占据连续两项。局部变量区包含对应方法的参数和局部变量。实例方法中隐含reference类型的变量this。方法参数按照声明顺序放到局部变量数组中,而局部变量可以任意决定放置顺序,甚至可以一个索引指代两个局部变量。

操作数栈 和局部变量区一样,组织为字长为单位的数组,数据存储也类似,但是不是通过索引访问,而是通过压栈和出栈来访问。Java虚拟机没有寄存器,程序计数器也无法被程序指令直接访问,因此指令主要是从操作数栈中而不是从寄存器中取得操作数。也可以从字节码流中跟随在操作码之后的字节或者常量池中取得。

帧数据区 除了局部变量区和操作数栈外,还需要一些数据来支持常量池解析、正常方法返回以及异常派发机制。这些信息都保存在帧数据区中。

9. 本地方法栈

大小不比固定,可以动态收缩或者扩展。线程调用本地方法的时候,虚拟机保持Java栈不变,不再压入新的帧,动态连接并直接调用指定的本地方法。 传递给该函数的参数以某个确定的顺序压入栈,返回值也以确定的方式传回调用者。和可能本地方法接口需要回调Java虚拟机中的Java方法 ,这种情形下该线程会保存本地方法栈的状态并进入另一个Java栈。

10. 执行引擎

在Java虚拟机规范中,执行引擎的行为使用指令集来定义。

指令集 方法的字节码流是由Java虚拟机的指令序列构成的。每一条指令包含一个单字节操作码,后面跟随0个或多个操作数。虚拟机取得操作数的地方包括跟随操作码的操作数、常量池中的项、当前帧的局部变量中的值、当前帧操作数栈顶的值。执行一条指令包含的任务之一就是决定下一条要执行的是什么命令。很多指令的下一个操作码就是当前操作码和操作数之后紧跟的那个字节。另一个指令如goto和return,执行引擎决定下一个操作码时把它当作当前执行指令的一部分。假如抛出异常,执行引擎将搜索合适的catch子句,决定下一条指令。

执行技术 实现可以使用多种执行技术:解释,即使编译,自适应优化,芯片级直接执行。由实现自由选择。最有意义也最迅速的执行技术之一就是自适应优化。监视代码执行情况,判断出某个方法是瓶颈的时候,启动一个后台线程,把字节码编译为本地代码并优化。Java程序运行时特征:方法调用和动态派发。

目录
相关文章
|
1月前
|
存储 Java 数据安全/隐私保护
【JVM】Java虚拟机栈(Java Virtual Machine Stacks)
【JVM】Java虚拟机栈(Java Virtual Machine Stacks)
46 0
|
1月前
|
监控 Oracle Java
《深入浅出Java虚拟机 — JVM原理与实战》带你攻克技术盲区,探索各大JVM虚拟机特色 —— JVM故障排除指南(先导篇)
《深入浅出Java虚拟机 — JVM原理与实战》带你攻克技术盲区,探索各大JVM虚拟机特色 —— JVM故障排除指南(先导篇)
52 0
|
14天前
|
安全 Java 编译器
Java 虚拟机加载 Java 类的过程
【6月更文挑战第7天】Java 是一门编译型语言,在完成代码的编写以后,需要使用 Java 编译器将源码编译成字节码文件,供虚拟机运行。在字节码被 Java 虚拟机执行之前,需要将对应的类进行加载。
44 3
|
1月前
|
存储 Java
深入理解Java虚拟机:JVM内存模型
【4月更文挑战第30天】本文将详细解析Java虚拟机(JVM)的内存模型,包括堆、栈、方法区等部分,并探讨它们在Java程序运行过程中的作用。通过对JVM内存模型的深入理解,可以帮助我们更好地编写高效的Java代码,避免内存溢出等问题。
|
1月前
|
缓存 算法 安全
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(二)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
31 0
|
1月前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
106 0
|
1天前
|
存储 Java C++
Java虚拟机(JVM)在执行Java程序时,会将其管理的内存划分为几个不同的区域
【6月更文挑战第24天】Java JVM管理内存分7区:程序计数器记录线程执行位置;虚拟机栈处理方法调用,每个线程有独立栈;本地方法栈服务native方法;Java堆存储所有对象实例,垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息;运行时常量池存储常量;直接内存不属于JVM规范,通过`java.nio`手动管理,不受GC直接影响。
11 5
|
1天前
|
存储 Java C++
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据,如局部变量和操作数;本地方法栈支持native方法;堆存放所有线程的对象实例,由垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息和常量;运行时常量池是方法区一部分,保存符号引用和常量;直接内存非JVM规范定义,手动管理,通过Buffer类使用。Java 8后,永久代被元空间取代,G1成为默认GC。
9 2
|
5天前
|
监控 算法 Java
Java虚拟机(JVM)使用多种垃圾回收算法来管理内存,以确保程序运行时不会因为内存不足而崩溃。
【6月更文挑战第20天】Java JVM运用多种GC算法,如标记-清除、复制、标记-压缩、分代收集、增量收集、并行收集和并发标记,以自动化内存管理,防止因内存耗尽导致的程序崩溃。这些算法各有优劣,适应不同的性能和资源需求。垃圾回收旨在避免手动内存管理,简化编程。当遇到内存泄漏,可以借助VisualVM、JConsole或MAT等工具监测内存、生成堆转储,分析引用链并定位泄漏源,从而解决问题。
16 4
|
7天前
|
算法 Java
Java垃圾回收(Garbage Collection,GC)是Java虚拟机(JVM)的一种自动内存管理机制,用于在运行时自动回收不再使用的对象所占的内存空间
【6月更文挑战第18天】Java的GC自动回收内存,包括标记清除(产生碎片)、复制(效率低)、标记整理(兼顾连续性与效率)和分代收集(区分新生代和老年代,用不同算法优化)等策略。现代JVM通常采用分代收集,以平衡性能和内存利用率。
33 3