美文网首页
【Java进阶营】Java虚拟机如何运行Java字节码?

【Java进阶营】Java虚拟机如何运行Java字节码?

作者: 梦幻小孩斋 | 来源:发表于2022-05-01 21:47 被阅读0次

一、Java的class文件的内容

1.首先编写一个简单的代码

public class StringDemo {

public static void main(String[] args) {

  String s=new String("hello world");

    System.out.println(s);

}

}

2.运行程序编译成class文件,class文件的查看可以用Java class文件分析工具 -- Classpy

3.这种字节码文件我们肯定看不懂,所以我们可以通过指令Javap来转换成我们人类可以看懂的

4.打开StringDemo.txt文件,即下图的内容

public class com.dada.demo.controller.StringDemo

minor version: 0

major version: 52

flags: ACC_PUBLIC, ACC_SUPER

Constant pool:

1 = Methodref #8.#24 // java/lang/Object."<init>":()V

2 = Class #25 // java/lang/String

3 = String #26 // hello world

4 = Methodref #2.#27 // java/lang/String."<init>":(Ljava/lang/String;)V

5 = Fieldref #28.#29 // java/lang/System.out:Ljava/io/PrintStream;

6 = Methodref #30.#31 // java/io/PrintStream.println:(Ljava/lang/String;)V

7 = Class #32 // com/dada/demo/controller/StringDemo

8 = Class #33 // java/lang/Object

9 = Utf8 <init>

10 = Utf8 ()V

11 = Utf8 Code

12 = Utf8 LineNumberTable

13 = Utf8 LocalVariableTable

14 = Utf8 this

15 = Utf8 Lcom/dada/demo/controller/StringDemo;

16 = Utf8 main

17 = Utf8 ([Ljava/lang/String;)V

18 = Utf8 args

19 = Utf8 [Ljava/lang/String;

20 = Utf8 s

21 = Utf8 Ljava/lang/String;

22 = Utf8 SourceFile

23 = Utf8 StringDemo.java

24 = NameAndType #9:#10 // "<init>":()V

25 = Utf8 java/lang/String

26 = Utf8 hello world

27 = NameAndType #9:#34 // "<init>":(Ljava/lang/String;)V

28 = Class #35 // java/lang/System

29 = NameAndType #36:#37 // out:Ljava/io/PrintStream;

30 = Class #38 // java/io/PrintStream

31 = NameAndType #39:#34 // println:(Ljava/lang/String;)V

32 = Utf8 com/dada/demo/controller/StringDemo

33 = Utf8 java/lang/Object

34 = Utf8 (Ljava/lang/String;)V

35 = Utf8 java/lang/System

36 = Utf8 out

37 = Utf8 Ljava/io/PrintStream;

38 = Utf8 java/io/PrintStream

39 = Utf8 println

{

public com.dada.demo.controller.StringDemo();

descriptor: ()V

flags: ACC_PUBLIC

Code:

  stack=1, locals=1, args_size=1

    0: aload_0

    1: invokespecial #1                  // Method java/lang/Object."<init>":()V

    4: return

  LineNumberTable:

    line 3: 0

  LocalVariableTable:

    Start  Length  Slot  Name  Signature

        0      5    0  this  Lcom/dada/demo/controller/StringDemo;

public static void main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)V

flags: ACC_PUBLIC, ACC_STATIC

Code:

  stack=3, locals=2, args_size=1

    0: new          #2                  // class java/lang/String

    3: dup

    4: ldc          #3                  // String hello world

    6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V

    9: astore_1

    10: getstatic    #5                  // Field java/lang/System.out:Ljava/io/PrintStream;

    13: aload_1

    14: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V

    17: return

  LineNumberTable:

    line 5: 0

    line 6: 10

    line 7: 17

  LocalVariableTable:

    Start  Length  Slot  Name  Signature

        0      18    0  args  [Ljava/lang/String;

      10      8    1    s  Ljava/lang/String;

}

SourceFile: "StringDemo.java"

5.上面的内容我们可以根据jvm指令码表,就知道什么意思啦

二、Java运行时数据区

1.方法区

Jvm用来存储加载类的信息、常量、静态变量、编译后的代码等数据

2.堆内存

Jvm启动时创建,存放对象的实例。垃圾回收器主要就是管理堆内存。

3.虚拟机栈

虚拟机栈,每个线程都在这个空间有一个私有的空间。线程栈由多个栈帧组成,一个线程执行一个或多个方法,一个方法对应一个栈帧。栈帧的内容包含:局部变量表、操作数栈、动态链接、方法返回地址、附加信息等。栈内存默认最大1M,超出则抛出StackOverflowError。

4.本地方法栈

和虚拟机栈功能类似,虚拟机栈是为虚拟机执行JAVA方法而准备的,本地方法栈是为虚拟机使用Native本地方法而准备的。

5.程序计数器

程序计数器记录当前线程执行字节码的位置,存储的是字节码指令地址,如果执行Native方法,则计数器值为空。每个线程在这个空间有一个私有的空间,占用内存空间很少。CPU同一时间,只会执行一条线程中的指令。JVM多线程会轮流切换并分配CPU执行时间的方式。为了线程切换后,需要通过程序计数器,来恢复正确的执行位置。

在了解上面的基础知识后,我们开始了解具体的执行过程。

三、Java虚拟机如何运行Java字节码?

标准JDK中的HotSpot是如何运行Java字节码的呢?(常见的虚拟机分三种1.HotSpot 2. JRockit 3.IBM的jvma)

需要从两个角度考虑:

虚拟机角度

底层硬件角度

1.1虚拟机角度

1.1.1从虚拟机角度是如何运行Java字节码的?

①首先会将Java代码编译成的class文件加载到JVM

②加载后的Java类会存放到方法区中。

③实际运行时,JVM会执行方法区内的代码。

④运行时,每当调用进入一个Java方法,JVM会在当前线程的Java方法栈中生成一个栈帧。

⑤退出执行的Java方法时,无论是不是正常返回,JVM都会弹出并舍弃掉当前线程的当前栈帧。

1.1.2栈帧是什么?

①用于存放局部变量、字节码的操作数

②栈帧的大小是提前计算好的。

③JVM不要求栈帧在内存空间内连续分布。

1.1.3JVM中内存组成部分有哪些?线程共享的是哪些部分?线程私有的是哪些部分?

线程共享:

①方法区:存放加载后的Java类

②堆:创建的对象实例

线程私有:

①Java方法栈: 面向Java方法

②本地方法栈: 面向C++写的native方法

③PC寄存器: 存放各个线程执行位置。

2.1硬件角度

2.1.1从硬件角度角度是如何运行Java字节码的?

①Java字节码无法直接执行

②JVM需要将字节码翻译成机器码

2.1.2JVM(如HotSpot)如何将字节码翻译成机器码?

两种方法:

①解释执行-逐条将字节码翻译成机器码执行

②即时编译(Just-In-Time compilation, JIT)-将一个方法中的字节码都编译成机器码后再执行。

总结:

Hello.java-->被编译成Hello.class,然后被加载到jvm的虚拟机里,存放到方法区内。实际运行代码时执行方法区的代码,每当调用进入一个Java方法,JVM会在当前线程的Java方法栈中生成一个栈帧,在栈帧内操作数栈根据指令码的顺序操作本地变量表来实现代码的执行,退出执行的Java方法时,无论是不是正常返回,JVM都会弹出并舍弃掉当前线程的当前栈帧。

讲解的部分可能不是很明白,大家可以多查阅一些资料,反复按照这个执行过程理解,我相信你很快就会形成自己的理解的。

相关文章

  • Dalvik虚拟机与java虚拟机的区别

    1.java虚拟机运行的是Java字节码,Dalvik虚拟机运行的是Dalvik字节码;传统的Java程序经过编译...

  • 2020-10-13 一键查看Java字节码

    何为 Java 字节码? Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定...

  • 使用 javap 命令查看 Java Class 文件的字节码内

    何为 Java 字节码? Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定...

  • jvm虚拟机介绍

    java虚拟机 java虚拟机是一台执行java字节码的虚拟计算机,它拥有独立的运行机制,其运行的java字节码也...

  • DVM执行 java 程序的工具

    jvm 执行字节码原理:java 程序运行时,是由一个 java 虚拟机来解释 java 字节码的,它将这些字节码...

  • java运行时数据区

    java程序在执行之前被编译成字节码文件,再由java虚拟机执行这些字节码文件是的java程序得以运行。java虚...

  • 《算法》1.1-习题解答

    1.答疑 Java字节码:运行于java虚拟机上。将程序抽象为字节码可以保证Java 程序员的代码能够运行在各种设...

  • JVM知识导图——Java代码运行机制

    概述 由 Java 和 C++ 运行方式的不同引入字节码和 Java 虚拟机的概念,最后详细描述虚拟机运行字节码的...

  • Java 基础

    Dalvik虚拟机与java虚拟机的区别 1.java虚拟机运行的是Java字节码,Dalvik虚拟机运行的是Da...

  • JVM内存模型

    JVM全称 Java Virtual Machine ,即Java虚拟机,是用于运行Java程序编译后的字节码文件...

网友评论

      本文标题:【Java进阶营】Java虚拟机如何运行Java字节码?

      本文链接:https://www.haomeiwen.com/subject/wreyyrtx.html