天天看点

教妹学Java(五):Java程序在编译和运行时发生了什么

大家好,我是沉默王二。本篇文章通过我和三妹的对话来谈一谈“Java程序在编译和运行时发生了什么”。

没见过这么有趣的标题吧?“语不惊人死不休”,没错,本篇文章的标题就是这么酷炫,接受不了的同学就别点进来看了,所谓好奇心害死猫;能够接受的同学我只能说你赚到了,你不仅能在阅读的过程中感受到思维的乐趣,还真的能学习到知识。下面就由我来介绍一下故事的背景吧。

我有一个漂亮如花的妹妹(见上图),她叫什么呢?我想聪明的读者朋友们都能猜得出:沉默王三,没错,年方三六。父母正考虑让她向我学习,做一名正儿八经的 Java 程序员。我期初是想反抗的,因为程序员这行业容易掉头发。但家命难为啊,与其反抗,不如做点更积极的事情,写点有趣的文章,教妹妹如何更快地掌握 Java 这门编程语言。毕竟程序员还算得上高薪(都是拿命换的啊)。

(铺垫结束,正文开始)

“二哥,看了上一篇 Hello World 的程序后,我很好奇,它是怎么在屏幕上打印出‘Hello World’呢?”

“三妹啊,‘Hello World’这段代码之所以能够正常工作,可以分为两大步骤:编译和运行,下面二哥会详细来说道说道。”

01、编译时发生了什么

现在,我们有一个名叫 Cmower.java 的文件,它的内容是这样的:

package main.java.com.cmower.java_demo.javatpoint.five;
public class Cmower {
    public static void main(String[] args) {
        System.out.println("大家好,我们沉默王二的妹妹沉默王三");
    }
}      

然后我们点击 IDEA 工具栏中的锤子按钮(Build Project)。此时可以在 src 的同级目录 target 的包路径下找到一个 Cmower.class 的文件(如果找不到的话,在目录上右键选择「Reload from Disk」)。

教妹学Java(五):Java程序在编译和运行时发生了什么

可以双击打开它。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.cmower.java_demo.javatpoint.five;
public class Cmower {
    public Cmower() {
    }
    public static void main(String[] args) {
        System.out.println("大家好,我们沉默王二的妹妹沉默王三");
    }
}      

IntelliJ IDEA 默认会用 Fernflower 反编译工具将字节码文件反编译为我们可以看得懂的 Java 源代码。

实际上,字节码文件 Cmower.class 的内容是下面这样的:

// class version 52.0 (52)
// access flags 0x21
public class com/cmower/java_demo/javatpoint/five/Cmower {
  // compiled from: Cmower.java
  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 3 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Lcom/cmower/java_demo/javatpoint/five/Cmower; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1
  // access flags 0x9
  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 5 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "\u5927\u5bb6\u597d\uff0c\u6211\u4eec\u6c89\u9ed8\u738b\u4e8c\u7684\u59b9\u59b9\u6c89\u9ed8\u738b\u4e09"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 6 L1
    RETURN
   L2
    LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1
}      

可以通过「View」中的「Show Bytecode」查看。

教妹学Java(五):Java程序在编译和运行时发生了什么

“三妹啊,懂了没?也就是说,在编译阶段,Java 编译器会将 Java 源代码文件编译为字节码文件。二哥再给你画幅图。”

教妹学Java(五):Java程序在编译和运行时发生了什么

02、运行时发生了什么

要想运行 Java 文件,可以点击 IDEA 工具栏中的运行按钮。此时会在底部视图中输出文字“大家好,我们沉默王二的妹妹沉默王三”。

教妹学Java(五):Java程序在编译和运行时发生了什么

那运行时都发生了什么呢?来画幅图吧!

教妹学Java(五):Java程序在编译和运行时发生了什么

字节码加载器:JVM 的一个子系统,用来载入字节码文件。

字节码验证:检查字节码中是否存在可能违法对象访问权限的非法代码。

指令执行:读取字节码流,执行指令。

“懂了没?三妹,字节码在运行前仍然做了不少工作,以防被篡改,保证安全性。”

“二哥,我懂了,你讲得可真棒!”