JVM剖析

0.前言

Java 是当今世界使用最广泛的技术平台之一。使用 Java 或 JVM 的一些技术包括:

  • Apache spark用于大数据处理,数据分析在JVM上运行;
  • 用于数据流的Apache NiFi在内部使用的也是 JVM;
  • 现代 Web 和移动应用程序开发中使用的React native使用 的也包含JVM 和 java 线程。

1.虚拟化

JVM 基于虚拟化技术(应用程序级虚拟化),它基本上是裸机硬件之上的抽象层。
传统计算机
虚拟化后的计算机
JVM 是应用程序级虚拟化的一个例子,它基本上是主机操作系统上的一个额外层。我们可以在操作系统内的沙箱中编译和运行 Java 程序,而不是直接使用操作系统例程。

2.代码编译与字节码

Java 代码在执行前要经过一系列转换。第一个编译过程从 java 编译器或javac开始,javac 将 java 代码转换为中间字节码,可以使用javap 等反汇编工具读取,字节码独立于计算机的平台架构,这是 java 编程语言具有可移植性的根本原因。

3.Java类结构

以下是使用 javap 反汇编后类文件的组成部分。

组成部分 说明
魔数(Magic Number) 0xCAFEBABE
类文件的版本(Magic Number) 类文件的次要和主要版本
常量池(Constang Pool) 类的常量池
访问标记(Access Flags) 例如类是否为抽象、静态等等
当前类(This Class) 当前类的名称
超类(Super Class) 超类的名称
接口(Inrerfaces) 类中所有的接口
方法(Methods) 类中所有的方法

每个类文件都以一个魔法数字开头,用于确认给定文件是类文件,接下来是类格式的版本,用于检查 JVM 版本与用于编译类文件的版本的兼容性。如果存在任何不匹配,则会抛出UnsupportedClassVersionError 。

其他组件用于存储类中使用的常量,访问标志存储访问说明符(公共、私有、抽象等)。类似地,其他组件存储类中使用的超类名称、接口和方法。

public class HelloWorld { 
	public static void main(String[] args) { 
		for (int i = 0; i < 10; i++) {
			 System.out.println("Hello World");
	    } 
	}
}

反汇编上面的 hello world 程序,结果如下是运行 hello world 程序,结果如下:

Classfile /home/xxxxxxxx/Documents/learning/java/jvm/HelloWorld.class
  Last modified 7 Oct 2021; size 478 bytes
  SHA-256 checksum 93080c0483aa97ce4c226f31f22ed95c633e0da00b997fe229bfa676f6fb53c0
  Compiled from "HelloWorld.java"
public class HelloWorld
  minor version: 0
  major version: 52
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #5                          // HelloWorld
  super_class: #6                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1

相应的机器语言指令将会是:

0: iconst_0
1: istore_1
2: iload_1
3: bipush        10
5: if_icmpge     22
8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
11: ldc           #3                  // String Hello World
13: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: iinc          1, 1
19: goto          2
22: return

源码解读:将常量存储到JVM堆栈中加载并与10进行比较,如果数字大于或等于10,则停止并退出函数,否则打印“ Hello world ”,直到满足条件。

4.解释和类加载

JVM类加载
将给定的源代码转换为字节后,JVM 将开始逐行解释类文件。JVM 是基于堆栈的解释器机器,因此 JVM 将使用内部堆栈来存储执行结果,而不是使用CPU 寄存器。此过程从将执行所需的所有类加载到方法缓存中开始。

4.1.类加载

代码执行中的三个重要过程:

  • 加载:加载执行所需的所有类。

  • 链接:验证类文件并解析所有符号引用。

  • 初始化:初始化程序中定义的所有静态变量。

4.1.1.类加载器的类型

  • 启动类加载器: Bootstrap 类加载器将加载源代码中的所有核心类,包括包含 main 函数的类。

  • 扩展类加载器:扩展类加载器以引导类作为其父类加载器。如果核心 Java 类中的任何方法被重写,则扩展类加载器将加载该类而不是原始类。

  • 应用程序类加载器:加载类路径中找到的所有类。如果类路径中未找到某个类,则会抛出classnotfound异常。

5.热点编译

C++ 实现遵循零开销原则:您不用的东西就不用付费。而且,您用的东西,您编写的代码再好不过了。Bjarne Stroustrup

ava 是一种蓝领语言。它不是博士论文材料,而是一种工作语言。James Gosling

热点编译是一种使 Java 代码执行速度比 C 和 C++ 等语言更快、更高效的方法。热点编译是一种方法,在解释过程进行时,分析器将开始收集有关执行的信息,基于此信息,即时 ( JIT)编译器将应用一组优化。

6.Java内存分配及内存管理

JVM 中运行的所有线程都会有一个公共堆,运行程序所需的所有内存都会从这个堆中分配,如果所需内存大于当前 JVM 堆内存,则会引发内存超出范围的异常。默认情况下,对象是可变的,除非它们由 final 关键字定义。

一个线程创建的任何对象都可以被另一个线程访问,可以通过一种称为互斥锁或互斥锁的技术来避免异常情况(一个线程引用的内存被另一个线程改变)。

7.JIT编译

此过程也称为配置文件引导优化。配置文件将跟踪当前正在运行的子系统的信息,当值达到某个阈值时将应用一组优化。一些配置文件引导优化策略如下:

  • 基于计数器的优化: Profiler 将保留方法调用次数的计数。如果计数达到大于某个阈值的值,则将缓存该方法,下次无需再次解释该方法,而是直接从缓存中获取该值;
  • 堆栈上替换:缓存不经常使用但包含循环的方法;
  • 内联:例如,用更高效的代码替换的过程。

相关推荐

  1. <span style='color:red;'>JVM</span><span style='color:red;'>剖析</span>

    JVM剖析

    2024-04-05 05:16:02      37 阅读
  2. JVM源码剖析之registerNatives方法

    2024-04-05 05:16:02       55 阅读
  3. JVM源码剖析之信号处理机制

    2024-04-05 05:16:02       40 阅读
  4. <span style='color:red;'>JVM</span>

    JVM

    2024-04-05 05:16:02      66 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-05 05:16:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-05 05:16:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-05 05:16:02       82 阅读
  4. Python语言-面向对象

    2024-04-05 05:16:02       91 阅读

热门阅读

  1. 图DP

    图DP

    2024-04-05 05:16:02      29 阅读
  2. Linux中关于网络方面常用命令行介绍

    2024-04-05 05:16:02       33 阅读
  3. Megatron-DeepSpeed-GPU-多机训练

    2024-04-05 05:16:02       42 阅读
  4. c++ new int[10]()会进行初始化.

    2024-04-05 05:16:02       33 阅读
  5. 【Python】【Flask】提交表单后报500错误

    2024-04-05 05:16:02       30 阅读
  6. css隐藏溢出隐藏的滚动条

    2024-04-05 05:16:02       35 阅读
  7. Pod安全上下文与Linux Capabilities浅析

    2024-04-05 05:16:02       29 阅读
  8. 递归与树的深度优先搜索:探索它们之间的关系

    2024-04-05 05:16:02       36 阅读
  9. Go语言中正则表达式简介

    2024-04-05 05:16:02       31 阅读
  10. Tokio强大的Rust异步框架

    2024-04-05 05:16:02       36 阅读
  11. 百问网FreeRTOS学习笔记第50到56讲

    2024-04-05 05:16:02       31 阅读