JVM内存布局、类加载机制及垃圾回收机制详解

一、JVM 简介

JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机
虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统
常见的虚拟机:JVM、VMwave、Virtual Box

JVM 和其他两个虚拟机的区别

  1. VMwaveVirtualBox通过软件模拟物理CPU的指令集,物理系统中会有很多的寄存器;
  2. JVM则是通过软件模拟Java字节码的指令集JVM中只是主要保留了PC寄存器,其他的寄存器都进行了裁剪。

JVM 是一台被定制过的现实当中不存在的计算机。

JVM出现的初心是为了"跨平台",“—次开发,到处运行”。

二、JVM 运行流程

JVM 是 Java 运行的基础,也是实现一次编译到处执行的关键,那么 JVM 是如何执行的呢?

JVM 运行流程
程序在执行之前先要把java代码转换成字节码(class文件),JVM 首先需要把字节码通过一定的方式:类加载器(ClassLoader) 把文件加载到内存中 运行时数据区(Runtime Data Area) ,而字节码文件是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器 执行引擎(Execution Engine)将字节码翻译成底层系统指令再交由CPU去执行,而这个过程中需要调用其他语言的接口 本地库接口(Native Interface) 来实现整个程序的功能,这就是这4个主要组成部分的职责与功能。

总结来看, JVM 主要通过分为以下 4 个部分,来执行 Java 程序的,它们分别是:

  1. 类加载器(ClassLoader)
  2. 运行时数据区(Runtime Data Area)
  3. 执行引擎(Execution Engine)
  4. 本地库接口(Native Interface)

三、 JVM运行时数据区域(内存布局)

JVM 运行时数据区域也叫内存布局,但需要注意的是它和 Java 内存模型((Java Memory Model,简称JMM)完全不同,属于完全不同的两个概念,它由以下 5 大部分组成:
在这里插入图片描述
JVM实际上是一个Java 进程,进程就是用来管理硬件资源的,比如内存。

JVM中内存来自于操作系统.JVM启动之后就会从操作系统这里申请到一大块内存,再针对这个内存划分出一些区域。

具体的内存布局:
在这里插入图片描述
对于堆区和方法区,在整个JVM中只存在一份,而程序计数器和栈区是跟进程绑定在一起的,一个java进程中,可能包含着多个线程,每个不同的线程都有独立的一份程序计数器和栈区。

  1. (运行时常量池):new的对象就放到堆中.
  2. 方法区:用来存储被虚拟机加载的类信息、常量、静态变量(静态成员)、即时编译器编译后的代码等数据的。
  3. (JVM栈/本地方法栈):局部变量.
  4. 程序计数器:程序计数器的作用:用来记录当前线程执行的行号的存的,它是个地址,描述当前线程接下来要执行的指令在内存的哪个地方

在这里插入图片描述

内存布局中的异常问题

堆溢出java.lang.OutOfMemoryError,循环创建对象,把对象加到List集合类里.(防止被GC回收)典型的情况就是不断地去new 对象而不去释放内存。
栈溢出StackOverflowError:写个递归方法,无限递归。

堆和栈的空间大小,都可以通过JVM(Java进程的命令行参数)来进行配置。
在这里插入图片描述
对引用类型的理解
可以把引用类型当作一个“低配指针”,但从更严谨的角度去看,引用并不是一个指针。Java的引用相当于堆C语言的指针功能进行了裁剪,Java中的引用只能用来解引用(如:使用 . 就是默认地解引用)和比较(==或!=) )。

四、JVM 类加载

关于.class文件的格式规范

类加载其实是JVM 中的一个非常核心的流程,做的事情就是把.class 文件,转成JVM 中的类对象。

要想完成类加载,必须要明确的知道.class文件中都有啥,按照.class文件中的规则进行解析。因此,编译器和类加载器(JVM)必须要商量好.class文件的格,而.class 文件的格式在 JVM虚拟机规范文档里面已经约定好了的,则编程语言的语法也可以理解为一种“协议”。

在JVM虚拟机规范文档中可以看到:
在这里插入图片描述
关于.class文件格式的规范:
在这里插入图片描述
可以看到,它把java代码中定义的一个类的核心信息都体现进去了,只不过这个文件的格式是二进制的。
因此,根据上述的格式我们也可以自己开发一个编程语言,然后编译就根据.class文件的格式一样,就可以直接在JVM中去解析执行了。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JVM内存模型分为以下几个区域: 1. 程序计数器:用于记录当前线程执行的字节码位置,是线程私有的。 2. Java虚拟机栈:用于存储每个方法的局部变量、操作数栈、动态链接、方法出口等信息,是线程私有的。 3. 本地方法栈:与虚拟机栈类似,用于存储本地方法的信息,是线程私有的。 4. Java堆:用于存储对象实例和数组,是所有线程共享的内存区域。Java堆分为新生代和老年代,新生代又分为Eden区、Survivor区1和Survivor区2。 5. 方法区:用于存储类的信息、常量、静态变量等数据,是所有线程共享的内存区域。 垃圾回收JVM自动管理内存的重要机制。垃圾回收可以清理无用的对象,释放内存空间,防止内存泄漏和OOM等问题。JVM垃圾回收主要有以下几种算法: 1. 标记-清除算法:首先标记出所有需要回收的对象,然后清除这些对象所占用的内存空间。这种算法容易产生内存碎片,影响空间利用率。 2. 复制算法:将可用内存空间分为两部分,每次只使用其中一部分。当这部分空间用完后,将所有存活的对象复制到另一部分空间中,然后清除原空间中所有对象。这种算法效率高,但空间利用率不高。 3. 标记-整理算法:先标记出所有需要回收的对象,然后将所有存活的对象向一端移动,然后清除边界外的所有对象。这种算法可以解决内存碎片问题,但效率比较低。 4. 分代收集算法:根据对象年龄的不同将Java堆分为不同的区域,每个区域采用不同的垃圾回收算法。新生代采用复制算法,老年代采用标记-整理算法或标记-清除算法。 JVM垃圾回收机制是自动的,但我们可以通过调整JVM的参数来影响垃圾回收的效率和行为。例如,可以通过-Xmx参数来设置Java堆的最大大小,可以通过-XX:+UseSerialGC参数来指定垃圾回收算法为串行收集器。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值