JVM真香系列:.java文件到.class文件

回复“000”获取大量电子书

认识JVM

什么是JVM

JVM 全称 Java Virtual Machine,也就是我们耳熟能详的 Java 虚拟机。它能识别 .class后缀的文件,并且能够解析它的指令,最终调用操作系统上的函数,完成我们想要的操作。

可能有部分小伙伴学习过C++,C++开发出来的程序,编译成二进制文件后,就可以直接执行了,操作系统是能够识别的。

但是咱们开的的Java程序就不一样了,使用javac命令编译出来的的.class文件之后,操作系统是不能识别的,需要对应JVM去做一个转换后,操作系统才能识别。

我们为什么不能像 C++ 一样,直接在操作系统上运行编译后的二进制文件呢?而非要搞一个处于程序与操作系统中间层的虚拟机呢?

这就是 JVM的过人之处了。大家都知道,Java 是一门抽象程度特别高的语言,提供了自动内存管理等一系列的特性。这些特性直接在操作系统上实现是不太可能的,所以就需要JVM 进行做一系列的转换。

大家一开始学Java的时候,就知道有个Write Once, Run Everywhere。就是我们编写了一个java文件经过编译成.class文件后,可以在各种系统中进行运行。

其实这里是有个前提的,我们需要在对应操作系统中安装对应的JVM,然后我们的.class文件就能运行了。

比如:Windows操作系统有对应的JDK安装版本、Linux也有对应的JDK安装版本等。

认识JDK

Java Development Kit (JDK) 是Sun公司(已被Oracle收购)针对Java开发员的软件开发工具包。自从Java推出以来,JDK已经成为使用最广泛的Java SDK(Software development kit)。

经非官方调查,目前JDK8是使用者最多的版本。

JDK14将在4月和7月收到安全更新,然后由9月到期的非LTS版本的JDK 15取代。JDK14包括16项新功能,例如JDK Flight Recorder事件流,模式匹配和开关表达式等特征。

JDK9之后,Oracle采用了新的发布周期:每6个月发布一个版本,每3年发布一个LTS版本。JDK14是继JDK9之后发布的第四个版本, 该版本为非LTS版本,最新的LTS版本为JDK11

下面是JDK版本情况

这个混个眼熟就行,随时关注JDK版本更新和新特性。

官网地址:https://www.oracle.com/java/

关于JDK安装这里就省略。

JDK、JRE、JVM的关系

上面已经说过JDKJVM的相关概念,

JRE全程Java Runtime Environment,是运行基于Java语言编写的程序所不可缺少的运行环境。也是通过它,Java的开发者才得以将自己开发的程序发布到用户手中,让用户使用。

三者到底是什么关系呢?

关于三者关系请看官网

https://docs.oracle.com/javase/8/docs/index.html

JDK中包含JRE,也包括JDK,而JRE也包括JDK。范围关系:JDK>JRE>JVM

".java"文件到".class"文件

`javac`命令

编写一个HelloWorld.java文件

内容就是一个Java入门

public class HelloWorld {
 public static void main(String[] args) {
  System.out.println("Hello world");
 }
}

打开CMD,进入当前目录,使用命令

javac HelloWorld.java

就编译出HelloWorld.class

编译过程

这个javac命令过程到底干了些什么呢?

javac背后大致做了这些操作

这个流程

1、词法分析

读取源代码,一个字节一个字节的读取,找出其中我们定义好的关键字(如Java中的if、else、for、while等关键词,识别哪些if是合法的关键词,哪些不是),这就是词法分析器进行词法分析的过程,其结果是从源代码中找出规范化的Token流。

2、语法分析

通过语法分析器对词法分析后Token流进行语法分析,这一步检查这些关键字组合再一次是否符合Java语言规范(如在if后面是不是紧跟着一个布尔判断表达式),词法分析的结果是形成一个符合Java语言规范的抽象语法树。

3、语义分析

通过语义分析器进行语义分析。语音分析主要是将一些难懂的、复杂的语法转化成更加简单的语法,结果形成最简单的语法(如将foreach转换成for循环 ,好有注解等),最后形成一个注解过后的抽象语法树,这个语法树更为接近目标语言的语法规则。

4、生成字节码

通过字节码生产器生成字节码,根据经过注解的语法抽象树生成字节码,也就是将一个数据结构转化为另一个数据结构。最后生成我们想要的.class文件。

使用十六进制查看class文件内容

我只用的是Notepad++,选中文本→插件→Converter→ASCII->HEX

class文件的开头就是

CAFEBABE

想要学习这里的十六进制的字节码的含义可以参考

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

javap查看class文件内容

javap是 Java class文件分解器,可以反编译(即对javac编译的文件进行反编译),也可以查看java编译器生成的字节码。

新建一个User.java源文件,经过javac编译后,生成User.classs

package com.tian.demo.test;

public class User {
 private int age = 22;
 private String name = "tian";

public int addAge() {
  return age = age + 1;
 }

public static void main(String[] args) {

}
}

使用javap命令

javap -v User.class >log.txt

打开log.txt

Classfile /D:/workspace/new/demo/src/main/java/com/tian/demo/test/User.class
  Last modified 2020-11-5; size 441 bytes
  MD5 checksum 2fa72d3f53bd9f138e0bfae82aba67e3
  Compiled from "User.java"
public class com.tian.demo.test.User
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref #6.#21   // java/lang/Object."<init>":()V
   #2 = Fieldref  #5.#22   // com/tian/demo/test/User.age:I
   #3 = String #23   // tian
   #4 = Fieldref  #5.#24   // com/tian/demo/test/User.name:Ljava/lang/String;
   #5 = Class  #25   // com/tian/demo/test/User
   #6 = Class  #26   // java/lang/Object
   #7 = Utf8   age
   #8 = Utf8   I
   #9 = Utf8   name
  #10 = Utf8   Ljava/lang/String;
  #11 = Utf8   <init>
  #12 = Utf8   ()V
  #13 = Utf8   Code
  #14 = Utf8   LineNumberTable
  #15 = Utf8   addAge
  #16 = Utf8   ()I
  #17 = Utf8   main
  #18 = Utf8   ([Ljava/lang/String;)V
  #19 = Utf8   SourceFile
  #20 = Utf8   User.java
  #21 = NameAndType  #11:#12  // "<init>":()V
  #22 = NameAndType  #7:#8 // age:I
  #23 = Utf8   tian
  #24 = NameAndType  #9:#10   // name:Ljava/lang/String;
  #25 = Utf8   com/tian/demo/test/User
  #26 = Utf8   java/lang/Object
{
  public com.tian.demo.test.User();
 descriptor: ()V
 flags: ACC_PUBLIC
 Code:
   stack=2, locals=1, args_size=1
   0: aload_0
   1: invokespecial #1   // Method java/lang/Object."<init>":()V
   4: aload_0
   5: bipush  22
   7: putfield   #2   // Field age:I
  10: aload_0
  11: ldc  #3   // String tian
  13: putfield   #4   // Field name:Ljava/lang/String;
  16: return
   LineNumberTable:
  line 3: 0
  line 4: 4
  line 5: 10

public int addAge();
 descriptor: ()I
 flags: ACC_PUBLIC
 Code:
   stack=3, locals=1, args_size=1
   0: aload_0
   1: aload_0
   2: getfield   #2   // Field age:I
   5: iconst_1
   6: iadd
   7: dup_x1
   8: putfield   #2   // Field age:I
  11: ireturn
   LineNumberTable:
  line 8: 0

public static void main(java.lang.String[]);
 descriptor: ([Ljava/lang/String;)V
 flags: ACC_PUBLIC, ACC_STATIC
 Code:
   stack=0, locals=1, args_size=1
   0: return
   LineNumberTable:
  line 13: 0
}
SourceFile: "User.java"

魔数与class文件版本
常量池
访问标志
类索引、父类索引、接口索引
字段表集合
方法表集合
属性表集合

然后JVM就可以读取这个User.class文件进行解析等一系列的操作。

以上就是我们的Java文件到class文件。

后续还会更新一系列JVM相关文章,敬请期待~

(0)

相关推荐

  • 0基础学Java(三)Java语言的特性

    Java语言的特性 1.简单性 在Java语言当中真正操作内存的是:JVM(Java虚拟机) 所有的java程序都是运行在Java虚拟机当中的. 而Java虚拟机执行过程中再去操作内存. 对于C或者C ...

  • JVM真香系列:轻松理解class文件到虚拟机(下)

    回复"000"获取大量电子书 类加载器 类加载器是很多人认为很硬的骨头.其实也没那么可怕,请听老田慢慢道来. 在装载(Load)阶段,通过类的全限定名获取其定义的二进制字节流,需要 ...

  • JVM真香系列:轻松理解class文件到虚拟机(上)

    回复"000"获取大量电子书 JVM初探 class文件到JVM中,就相当于我们吃饭,食物吃进了肚子里,不同的营养成分被身体不同的器官吸收. 查找class文件并导入到JVM中 ( ...

  • JVM真香系列:图解垃圾回收器

    回复"000"获取大量电子书 不知不觉,JVM系列已经到回收算法的实现了. 本文主要内容 先普及三个概念: 并行收集:指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态. 并 ...

  • JVM真香系列:如何判断对象是否可被回收?

    回复"000"获取大量电子书 在JVM中程序寄存器.Java虚拟机栈.本地方法栈,这三个区是随着线程的创建而创建,随着线程结束而销毁. 其实就是这三个的生命周期和线程的生命周期一样 ...

  • JVM真香系列:堆内存详解

    回复"000"获取大量电子书 前面的文章中已经有所提到过堆,只是大致介绍了一下.本文就来详细聊聊JVM中的堆. 在 JVM中,堆被划分成两个不同的区域:新生代 ( Young ). ...

  • JVM真香系列:方法区、堆、栈之间到底有什么关系

    回复"000"获取大量电子书 栈指向堆 如果在栈帧中有一个变量,类型为引用类型,比如: package com.tian.my_code.test; public class Jv ...

  • JVM真香系列:轻松掌握JVM运行时数据区

    回复"000"获取大量电子书 前面我们讲了从java源文件到class文件,在从class文件到JVM.那么今天继续聊JVM是如何布局的. JVM运行时数据区有几个?看看官网是就知 ...

  • 真香系列之盗版的WPS?

    ‍‍ ‍‍逃离工地后明显觉得能写的素材少了. 我琢磨了下原因,发现是因为到格子间后,面对的就那几个固定的同事,故事有限:有趣程度也远比不上工地上的那些个吃喝嫖赌抽.吃拿卡要偷的主儿. 这就让我有点伤脑 ...

  • 10万元左右就能买!这款合资SUV实锤"真香"系列

    如何在有限的预算下,购买一辆称心如意的新座驾?成为当前年轻消费者普遍的难题.以10-15万级别的SUV为例,这里面既有主打高配置的国产SUV,也有主打品牌和品质的合资SUV,到底哪款车最值得年轻人入手 ...