大家好,我是沉默王二。本篇文章通过我和三妹的对话来谈一谈“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」)。
可以双击打开它。
// // 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 源代码文件编译为字节码文件。二哥再给你画幅图。”
02、运行时发生了什么
要想运行 Java 文件,可以点击 IDEA 工具栏中的运行按钮。此时会在底部视图中输出文字“大家好,我们沉默王二的妹妹沉默王三”。
那运行时都发生了什么呢?来画幅图吧!
字节码加载器:JVM 的一个子系统,用来载入字节码文件。
字节码验证:检查字节码中是否存在可能违法对象访问权限的非法代码。
指令执行:读取字节码流,执行指令。
“懂了没?三妹,字节码在运行前仍然做了不少工作,以防被篡改,保证安全性。”
“二哥,我懂了,你讲得可真棒!”