初识JVM(JVM运行流程,JVM运行时数据区,内存布局中的异常)

简介: JVM(Java Virtual Machine),为Java虚拟机,虚拟机是指通过软件模拟一个具有完整的硬件功能并且运行在完全隔离的环境中的完整的计算机系统,JVM是一台被定制过的现实中不存在的计算机。

🚗一. JVM概述

JVM(Java Virtual Machine),为Java虚拟机,虚拟机是指通过软件模拟一个具有完整的硬件功能并且运行在完全隔离的环境中的完整的计算机系统,JVM是一台被定制过的现实中不存在的计算机


注意:选择题可能考


🚩HotSpot VM:


现在广泛使用的虚拟机,HotSpot指热点代码探测技术,它能通过计数器找到最具有编译价值的代码,触发即时编译(JIT),通过编译器与解释器协同工作,在最优化的程序响应时间与最佳执行性能中取得平衡值


对JIT即时编译的解释:热点代码比如一个while循环,每次循环边运行边翻译,效率低,JIT即时编译就将此热点代码直接编译为机器码,后面就不需要翻译可以直接执行,效率高


🚓二. JVM的运行流程

🚦一段Java代码是如何运行起来的呢?


通过java 类名会启动一个Java进程,系统为进程分配一块内存空间来执行进程的代码指令

有一条指令就会创建Java虚拟机

在Java虚拟机中会启动一个线程来执行main方法

Java虚拟机把class字节码的内容翻译为机器码,CPU来运行机器码


🏁整体看Java代码从编译到运行时的流程:

image.png

🚧说明:


Java程序在执行前先把Java代码转换为.class字节码,JVM先通过类加载器把字节码文件加载到Java进程内存的运行时数据区, 再将字节码翻译为底层系统指令所能识别的机器码,再交给CPU执行


🚕三. JVM运行时数据区(面试常考重点)

JVM运行时数据区也叫作内存布局,由堆区,方法区,虚拟机栈,本地方法栈,程序计数器这五部分组成


🚩jdk1.8把方法区称为元数据区,元数据区的常量池为运行时常量池

image.png


🛹1. 堆区(线程共享)

堆是最大的内存区域,程序运行时创建,程序退出时销毁,new创建对象都保存在堆中,字符串常量池也保存在堆中


堆中的新生代和老生代:新生代放新创建的对象,当经历了一定的GC次数之后还存活的对象就存放在老生代里


🛼2. 虚拟机栈(线程私有)

虚拟机栈的生命周期和线程相同,随着线程的创建而创建,线程的销毁而销毁,Java虚拟机栈描述的是Java方法执行的内存模型


每个方法都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息,常说的栈内存就指的是虚拟机栈


🛸局部变量表:存放了编译器可知的基本数据类型,对象引用,方法参数,局部变量表所需的内存空间在编译期间就被分配好,进入一个方法,所需的局部变量表空间是确定的,在方法执行期间,不会改变局部变量表的大小

🛸操作数栈:每个方法都会生成一个先进后出的操作栈

🛸动态链接:指向运行时常量池的方法引用

🛸方法返回地址:PC寄存器的地址


结合代码示例理解栈和栈帧

public class Test {
    public static void swap(int m,int n){
        int temp = m;
        m = n;
        n = temp;
    }
    public static void main(String[] args) {
        int m = 10;
        int n = 20;
        swap(m,n);
        System.out.println("m:"+m+" "+"n:"+n);
    }
}

执行结果:m还是10,n还是20,没有发生交换

image.png

🚲3. 本地方法栈(线程私有)

Java虚拟机可能调用系统函数(本地方法),也可能调用native方法(本地方法),native方法底层使用c/c++写的,本地方法也需要一定的内存空间,本地方法栈就是用来保存这些本地方法的


🛵4. 程序计数器(线程私有)

程序计数器用来记录当前线程执行代码的行号


如果当前线程执行的是Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址

如果当前线程执行的是native方法,这个计数器的值为空


程序计数器是一块比较小的内存空间,🚩是唯一一个在JVM规范中没有规定任何OOM情况的区域


🏍️5. 方法区/元数据区(线程共享)

用来存储被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据


🚁jdk1.7,称为方法区,在Java进程的内存中

🚁jdk1.8,称为元空间,属于本地内存(不在Java进程内存中)


🚨运行时常量池:存放字面量与符号引用


🪂字面量:字符串(jdk1.8移动到堆中),final常量,基本数据类型的值

🪂符号引用:类和结构的完全限定名,字段的名称和描述符,方法的名称和描述符


🚙四. 内存布局中的异常

🛹1. 堆溢出

可以设置JVM参数-Xms:设置堆的最小值,-Xmx:设置堆的最大值

微信图片_20221029151836.jpg

设置参数为:-Xmx20m -Xms20m -XX:+HeapDumpOnOutOfMemoryError

import java.util.ArrayList;
import java.util.List;
public class Test {
    static class OOMObject {
    }
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();
        while(true){
            list.add(new OOMObject());
        }
    }
}

运行上面代码观察堆溢出(堆OOM):OutOfMemoryError

微信图片_20221029152250.jpg

这里还需进一步分析是内存泄漏还是内存溢出


🚁内存泄漏:对象等数据不用但是也无法被GC,比如io资源未释放,资源的内存就无法被回收,就可能导致内存泄漏


🚁内存溢出:内存对象还存活,此时根据JVM堆参数与物理内存相比较检查是否应该把JVM堆内存调大,或检查对象的生命周期是否过长


🛼2. 栈溢出

如果线程请求的栈深度大于虚拟机所允许的最大深度,会抛出StackOverFlow异常


运行下面代码,观察栈溢出:StackOverflowError

public class Test {
    public static void method(){
        int a = 0;
        method();
    }
    public static void main(String[] args) {
        method();
    }
}

栈帧调用太深,一般在递归中出现,如递归没有返回值等等

微信图片_20221029152329.jpg

相关文章
|
1月前
|
存储 算法 Oracle
不好意思!耽误你的十分钟,JVM内存布局还给你
先赞后看,南哥助你Java进阶一大半在2006年加州旧金山的JavaOne大会上,一个由顶级Java开发者组成的周年性研讨会,公司突然宣布将开放Java的源代码。于是,下一年顶级项目OpenJDK诞生。Java生态发展被打开了新的大门,Java 7的G1垃圾回收器、Java 8的Lambda表达式和流API…大家好,我是南哥。一个Java学习与进阶的领路人,相信对你通关面试、拿下Offer进入心心念念的公司有所帮助。
不好意思!耽误你的十分钟,JVM内存布局还给你
|
1月前
|
存储 Java 程序员
JVM自动内存管理之运行时内存区
这篇文章详细解释了JVM运行时数据区的各个组成部分及其作用,有助于理解Java程序运行时的内存布局和管理机制。
JVM自动内存管理之运行时内存区
|
26天前
|
存储 算法 Java
JVM组成结构详解:类加载、运行时数据区、执行引擎与垃圾收集器的协同工作
【8月更文挑战第25天】Java虚拟机(JVM)是Java平台的核心,它使Java程序能在任何支持JVM的平台上运行。JVM包含复杂的结构,如类加载子系统、运行时数据区、执行引擎、本地库接口和垃圾收集器。例如,当运行含有第三方库的程序时,类加载子系统会加载必要的.class文件;运行时数据区管理程序数据,如对象实例存储在堆中;执行引擎执行字节码;本地库接口允许Java调用本地应用程序;垃圾收集器则负责清理不再使用的对象,防止内存泄漏。这些组件协同工作,确保了Java程序的高效运行。
17 3
|
29天前
|
消息中间件 设计模式 安全
多线程魔法:揭秘一个JVM中如何同时运行多个消费者
【8月更文挑战第22天】在Java虚拟机(JVM)中探索多消费者模式,此模式解耦生产与消费过程,提升系统性能。通过`ExecutorService`和`BlockingQueue`构建含2个生产者及4个消费者的系统,实现实时消息处理。多消费者模式虽增强处理能力,但也引入线程安全与资源竞争等挑战,需谨慎设计以确保高效稳定运行。
58 2
|
19天前
|
C# UED 开发者
WPF动画大揭秘:掌握动画技巧,让你的界面动起来,告别枯燥与乏味!
【8月更文挑战第31天】在WPF应用开发中,动画能显著提升用户体验,使其更加生动有趣。本文将介绍WPF动画的基础知识和实现方法,包括平移、缩放、旋转等常见类型,并通过示例代码展示如何使用`DoubleAnimation`创建平移动画。此外,还将介绍动画触发器的使用,帮助开发者更好地控制动画效果,提升应用的吸引力。
41 0
|
1月前
|
算法 Java
JVM常用运行时参数说明
JVM常用运行时参数说明
|
1月前
|
Java Docker 索引
记录一次索引未建立、继而引发一系列的问题、包含索引创建失败、虚拟机中JVM虚拟机内存满的情况
这篇文章记录了作者在分布式微服务项目中遇到的一系列问题,起因是商品服务检索接口测试失败,原因是Elasticsearch索引未找到。文章详细描述了解决过程中遇到的几个关键问题:分词器的安装、Elasticsearch内存溢出的处理,以及最终成功创建`gulimall_product`索引的步骤。作者还分享了使用Postman测试接口的经历,并强调了问题解决过程中遇到的挑战和所花费的时间。
|
1月前
|
存储 算法 Java
JVM自动内存管理之垃圾收集算法
文章概述了JVM内存管理和垃圾收集的基本概念,提供一个关于JVM内存管理和垃圾收集的基础理解框架。
JVM自动内存管理之垃圾收集算法
|
1月前
|
存储 安全 Java
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别;什么是程序计数器,堆,虚拟机栈,栈内存溢出,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
|
1月前
|
存储 安全 Java
JVM内存结构
这篇文章详细介绍了Java虚拟机(JVM)的内存结构,包括类的加载过程、类加载器的双亲委派机制、沙箱安全机制、程序计数器、Java栈、Java堆、本地方法和本地方法栈等关键组件及其作用。
JVM内存结构

热门文章

最新文章