JVM的运行原理

目录

1.概念

2.JVM运行机制

3.JVM执行流程 

4.JVM运行时数据区

什么是线程私有?

OOM(内存溢出)

4.1 堆:也叫运行时数据区,线程共享

4.2 方法区:线程共享

4.3 Java虚拟机栈:线程私有,描述Java方法的执行过程

4.4 本地方法栈:线程私有

4.5 程序计数器:线程私有,无内存溢出问题(OOM)

5.内存布局中的异常问题

5.1 Java堆溢出

5.2 虚拟机栈和本地方法栈溢出

5.3 OOM 与 内存泄漏

5.4 OOM 与 StackOverflow



1.概念

JVM(Java Vritual Machine)是运行于Java字节码的虚拟机,包括一套字节码指令集、一组程序寄存器、一个虚拟机栈、一个虚拟机堆、一个方法区和一个垃圾回收器。JVM运行在操作系统之上,不与硬件设备直接交互。

2.JVM运行机制

Java源文件在通过编译器后被编译成相应的 .Class 文件(字节码文件),.Class 文件又被JVM中的解释器编译成机器码在不同的操作系统(Windows、Linux、Mac)上运行。每种操作系统的解释器是不同的,但基于解释器实现的虚拟机是相同的,这也是Java能够跨平台的原因。

通过 java.exe 程序,来运行 xxx.class,启动时就创建一个JVM

3.JVM执行流程 

 其中:

  • 类加载器子程序用于将编译好的 .Class 文件加载到JVM中;
  • 运行时数据区用于存储在JVM运行过程中产生的数据,包括程序计数器、方法区、本地方法区、虚拟机栈和虚拟机堆;
  • 执行引擎包括即时编译器和垃圾回收器,即时编译器用于将Java字节码编译成具体的机器码,垃圾回收器用于回收在运行过程中不再使用的对象;
  • 本地接口库用于调用操作系统中的本地方法库完成具体的操作指令。

4.JVM运行时数据区

什么是线程私有?

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

OOM(内存溢出)

指存放数据的大小,超出该区域的内存大小。

运行时数据区域中,除了程序计数器,其他都可能发生OOM

4.1 堆:也叫运行时数据区,线程共享

在JVM运行过程中创建的对象和产生的数据都被存储在堆中,堆是被线程共享的内存空间,也是垃圾收集器进行垃圾回收的最主要的内存区域。由于现代JVN采用分代收集算法,因此Java堆从GC(Garbage Collection,垃圾回收)的角度还可以细分为:新生代、老年代和永久代

堆的作用:程序中创建的所有对象都在保存在堆中(数组也是对象)

4.2 方法区:线程共享

方法区的作用:用来存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据的。

在《Java虚拟机规范中》把此区域称之为“方法区”,而在 HotSpot 虚拟机的实现中,在 JDK 7 时此区域叫做永久代(PermGen),JDK 8 中叫做元空间(Metaspace)。

4.3 Java虚拟机栈:线程私有,描述Java方法的执行过程

  1. 栈的生命周期和线程相同:创建线程,就创建栈;销毁线程,就销毁这个栈
  2. 线程执行某个方法,就创建该方法栈桢(入栈),方法返回,就出栈 

用于保存 局部变量表——变量(=左边的),基础数据类型的值(如果是基础数据类型,=右边的也在虚拟机栈)

Java 虚拟机栈的作用:Java 虚拟机栈的生命周期和线程相同,Java 虚拟机栈描述的是 Java 方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。咱们常说的堆内存、栈内存中,栈内存指的就是虚拟机栈。

4.4 本地方法栈:线程私有

  • 调用Java方法,就是创建栈帧,放在线程的Java虚拟机栈中
  • 调用其他方法的函数,就是使用本地方法栈

4.5 程序计数器:线程私有,无内存溢出问题(OOM)

程序计数器是一块很小的内存空间,用于存储当前运行的线程所执行的字节码的行号指令器。

用于标识程序的行号

5.内存布局中的异常问题

5.1 Java堆溢出

Java堆用于存储对象实例,只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免来GC清除这些对象,那么在对象数量达到最大堆容量后就会产生内存溢出异常。

内存泄漏 : 泄漏对象无法被GC。

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

5.2 虚拟机栈和本地方法栈溢出

关于虚拟机栈会产生的两种异常:

  • 如果线程请求的栈深度大于虚拟机所允许的最大深度,会抛出StackOverFlow异常
  • 如果虚拟机在拓展栈时无法申请到足够的内存空间,则会抛出OOM异常

5.3 OOM 与 内存泄漏

内存泄漏:线程生命周期太长,导致始终只用一些不常使用的数据(这些数据gc无法正常回收),随着时间越来越长,最终导致OOM;

5.4 OOM 与 StackOverflow

某个线程,调用方法,创建方法栈帧,入栈,如果栈中的栈帧超过jvm规定的数量,就会报这个异常。

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值