性能文章>【译】关于JVM — JAVA虚拟机的一篇简单科普>

【译】关于JVM — JAVA虚拟机的一篇简单科普转载

3周前
192414

你觉得呢?什么是虚拟机?

在我们看到JVM的概念之前,让我们看看虚拟机(VM)的概念。

物理节点是基本O.S

什么是Java虚拟机(JVM)?

在C和C++等编程语言中,代码首先编译成特定于平台的机器代码。这些语言被称为编译语言。

与文章无关,只是为了让你的头脑摆脱紧张,只是笑和学习。

Java虚拟机架构

JVM由三个不同的组件组成:

  1. 类加载器
  2. 运行时数据区域
  3. 执行引擎
只是为了好玩和学习

类加载器

当您编译.java源文件时,它会作为.class文件转换为字节代码。当您尝试在程序中使用此类时,类加载程序会将其加载到主内存中。

正在加载 —

加载涉及获取具有特定名称的类或接口的二进制表示(字节码),并从中生成原始类或接口。

链接 —

类加载到内存中后,它会经历链接过程。链接类或接口涉及将程序的不同元素和依赖项组合在一起。

private static final boolean doit = true;

初始化 —

初始化涉及执行类或接口的初始化方法(称为<clinit>)。这可以包括调用类的构造函数,执行静态块,并为所有静态变量分配值。这是类加载的最后阶段。

private static final boolean doit= true;

注意—JVM是多线程的。可能会发生多个线程试图同时初始化同一类。这可能会导致并发问题。您需要处理线程安全,以确保程序在多线程环境中正常工作。

:)))

运行时数据区域

运行时数据区域内有五个组件

方法区域—

所有类级数据,如运行时常量池、字段和方法数据,以及方法和构造函数的代码,都存储在这里。

堆面积—

所有对象及其相应的实例变量都存储在这里。这是分配所有类实例和数组内存的运行时数据区域。

注意:由于方法和堆区域为多个线程共享相同的内存,因此存储在这里的数据不是线程安全的。

堆栈区域-

每当在JVM中创建新线程时,也会同时创建一个单独的运行时堆栈。所有局部变量、方法调用和部分结果都存储在堆栈区域中。

  • 局部变量—每个帧都包含一个称为其局部变量的变量数组。所有局部变量及其值都存储在这里。此数组的长度在编译时确定。
  • 操作数堆栈—每个帧都包含一个最后入先出(LIFO)堆栈,称为其操作数堆栈。这充当执行任何中间操作的运行时工作区。此堆栈的最大深度在编译时确定。
  • 帧数据—与该方法对应的所有符号都存储在这里。在出现异常时,这也存储捕获块信息。

注意:由于堆栈区域不是共享的,因此它本质上是线程安全的。

笑着学习 :))

程序计数器(PC)寄存器-

JVM同时支持多个线程。每个线程都有自己的PC寄存器来保存当前执行的JVM指令的地址。指令执行后,PC寄存器将更新为下一个指令。

原生方法堆栈-

JVM包含支持本机方法的堆栈。这些方法是用Java以外的语言编写的,例如C和C++。对于每个新线程,还分配一个单独的本机方法堆栈。

执行引擎—

一旦字节码加载到主内存中,并且运行时数据区域中有详细信息,下一步就是运行程序。执行引擎通过执行每个类中存在的代码来处理这个问题。

口译员—

解释器逐行读取和执行字节码指令。由于逐行执行,解释器相对较慢。

JIT编译器—

JIT编译器克服了口译员的缺点。执行引擎首先使用解释器执行字节代码,但当它找到一些重复的代码时,它使用JIT编译器。

  1. 中级代码生成器 - 生成中间代码
  2. 代码优化器—优化中间代码以获得更好的性能
  3. 目标代码生成器-将中间代码转换为本机代码
  4. 分析器—查找热点(重复执行的代码)

注意:JIT编译器编译代码比解释器逐行解释代码花费的时间要多。如果您只运行一次程序,使用解释器会更好。

笑和学习

垃圾收集器—

垃圾收集器(GC)从堆区收集和删除未引用的对象。这是通过销毁运行时未使用的内存自动回收它们的过程。

  1. 标记—在此步骤中,GC标识内存中未使用的对象
  2. 扫描—在此步骤中,GC删除上一阶段确定的对象
  1. 串行GC—这是GC最简单的实现,专为在单线程环境中运行的小型应用程序而设计。它使用单个线程进行垃圾收集。当它运行时,它会导致一个“停止世界”事件,整个应用程序被暂停。使用串行垃圾收集器的JVM参数是-XX:+UseSerialGC
  2. 并行GC—这是JVM中GC的默认实现,也称为吞吐量收集器。它使用多个线程进行垃圾收集,但在运行时仍然暂停应用程序。使用并行垃圾收集器的JVM参数是-XX:+UseParallelGC
  3. 垃圾优先(G1)GC——G1GC专为具有大堆尺寸(超过4GB)的多线程应用程序而设计。它将堆划分为一组大小相等的区域,并使用多个线程扫描它们。G1GC识别垃圾最多的区域,并首先在该区域执行垃圾收集。使用G1垃圾收集器的JVM参数是-XX:+UseG1GC

Java本机接口(JNI)-

有时,有必要使用本机(非Java)代码(例如C/C++)。这可以在我们需要与硬件交互或克服Java中的内存管理和性能约束的情况下。Java支持通过Java本机接口(JNI)执行本机代码。

原生方法库-

原生方法库是用其他编程语言编写的库,如C、C++和汇编。这些库通常以.dll.so文件的形式存在。这些本机库可以通过JNI加载。

常见的JVM错误

  • ClassNotFoundExcecption — 当类加载程序尝试使用Class.forName()ClassLoader.loadClass()ClassLoader.findSystemClass()加载类,但没有找到具有指定名称的类的定义时,就会发生这种情况。
  • NoClassDefFoundError — 当编译器成功编译了类,但Class Loader无法在运行时找到类文件时,就会发生这种情况。
  • OutOfMemoryError — 当JVM因内存不足而无法分配对象,并且垃圾收集器无法提供更多内存时,就会发生这种情况。
  • StackOverflowError — 如果JVM在处理线程时创建新堆栈帧时空间不足,就会发生这种情况。

结论

在此过程中,我们讨论了Java虚拟机的架构及其各种组件。当我们的代码工作时,它是如何工作的。

点赞收藏
金色梦想

终身学习。

请先登录,查看1条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

没有二十年功力,写不出Thread.sleep(0)这一行“看似无用”的代码!

没有二十年功力,写不出Thread.sleep(0)这一行“看似无用”的代码!

JVM 常见线上问题:CPU100%、内存泄露的问题排查

JVM 常见线上问题:CPU100%、内存泄露的问题排查

【全网首发】微服务10:系统服务熔断、限流

【全网首发】微服务10:系统服务熔断、限流

【全网首发】MQ-消息堆积-JDK Bug导致线程阻塞案例分析

【全网首发】MQ-消息堆积-JDK Bug导致线程阻塞案例分析

FullGC没及时处理,差点造成P0事故

FullGC没及时处理,差点造成P0事故

【全网首发】一次想不到的 Bootstrap 类加载器带来的 Native 内存泄露分析

【全网首发】一次想不到的 Bootstrap 类加载器带来的 Native 内存泄露分析

4
1