Thoughts sparked by HelloWorld

new home address

1. Handwritten source program

  When we open any book on Java learning, it will tell us to use Notepad or other text editor to write a simple small program, then javac class name, compile it, and a .calss file with the same name will be generated under the same file; We first write a HelloWorld.java here, the code is as follows:

 

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

 

 

.class file deserialization, the code is as follows:

 

package com.tao.study.one;

public class HelloWorld {
    public HelloWorld() {
    }

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

 

We use the cmd command to open our compiled .class file. The cmd command is: javap -v class name. The internal code of HelloWorld.class is as follows:

Classfile /E:/DataBase/Idea/JavaStudy/out/production/JavaStudy/com/tao/study/one/HelloWorld.class
  Last modified 2017-12-3; size 570 bytes
  MD5 checksum e34e8917fa1c76751b4ea9a2f491d17a
  Compiled from "HelloWorld.java"
public class com.tao.study.one.HelloWorld
  minor version: 0 // minor version number
  major version: 52 //compiler version number == jdk1.8
  flags: ACC_PUBLIC, ACC_SUPER
//constant pool
Constant pool:
   #1 = Methodref          #6.#20         // java/lang/Object."<init>":()V
   #2 = Fieldref           #21.#22        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #23            // Hello World!
   #4 = Methodref          #24.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #26            // com/tao/study/one/HelloWorld
   #6 = Class              #27            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8()
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8 LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/tao/study/one/HelloWorld;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               SourceFile
  #19 = Utf8 HelloWorld.java
  #20 = NameAndType        #7:#8          // "<init>":()V
  #21 = Class              #28            // java/lang/System
  #22 = NameAndType        #29:#30        // out:Ljava/io/PrintStream;
  #23 = Utf8               Hello World!
  #24 = Class              #31            // java/io/PrintStream
  #25 = NameAndType        #32:#33        // println:(Ljava/lang/String;)V
  #26 = Utf8               com/tao/study/one/HelloWorld
  #27 = Utf8               java/lang/Object
  #28 = Utf8               java/lang/System
  #29 = Utf8               out
  #30 = Utf8               Ljava/io/PrintStream;
  #31 = Utf8               java/io/PrintStream
  #32 = Utf8               println
  #33 = Utf8               (Ljava/lang/String;)V
{
  public com.tao.study.one.HelloWorld();
    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 6: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/tao/study/one/HelloWorld;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Hello World!
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 8: 0
        line 9: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
}
SourceFile: "HelloWorld.java"

 
2. Asking questions 

  Seeing the above results, our first impression must be, woc, why is it so amazing, what is going on here? Then we will explore them with these questions. After the last operation on Baidu, we know that javac is a compiler that comes with java, which converts the java language specification into a bytecode file (.class) that can be recognized by the JVM. file); this is even more confusing, and I even want to skip it, someone who has come over tells you, don’t be like this. Let's summarize the problems here, and then explore what the world of java is like.

The questions are:

1. What is the javac compiler? What does it do? How does it work?
2. Why load the bytecode file into the JVM? How is the bytecode file loaded into the JVM?
3. What is JVM? How does it work?

3. Solve questions

  Are you a little excited to see these questions? It turns out that there are so many things that java can learn, so let's start our exploration journey. Problems need to be solved one by one, let's study them in order!

Compilation principle

1.1  javac是java语言自带的一种编译器,我们都知道java有自己的语言规范,写错了一小处代码,整个项目都会无法运行,这就是规范的魅力,无规矩不成方圆,代码世界中同样如此,每一门语言都是一个王国,我们都是它的臣民;但是java语言不是机器语言,我们的机器是无法识别的,于是我们的java国王大手一挥创建了外交部,让javac负责这个部门,让它负责对外交流,但是javac这个小伙发现一个人的力量是有限的,要充分发挥自己的部长身份,于是他找到自己的得力干将JVM,让他负责与机器王国进行交流;每当国王发布新的命令的时候(.java文件),javac就将其编译成字节码文件,然后直接丢给自己的小弟JVM,自己只负责与国王(java类)对话交流;

1.2  Java的编译环节分为四个步骤,绝大部分的编译器也是这样设计的,四个步骤依次为:

  • 词法解析
  • 语法解析
  • 语义解析
  • 生成字节码
      编译器的功能就是将java代码翻译成JVM规范下的字节码文件,最重要的点是符合jvm规范,我们的翻译过程也主要是围绕着从一个规范到另一个规范的过程展开;
    1.2.1  词法解析:
    词法解析的作用就是生成符合java语法规范的Token序列;

    注释:Token序列就是一组对应源码字符集合的单词序列,其实上就是一个枚举类型,内部定义了许多符合java语法规范并与源码字符集合相对应的枚举常量;

  这时我们肯定会非常好奇,java源码是如何转换成Token序列的呢?java的源码又是如何和已经生成的Token序列保持一个长久的对应关系呢?
  词法解析器在将源码翻译成Token序列之前,会先把这个源码字符集合转化为一个Name对象,每一个源码字符集合都是一个Name对象;Keywsords这个类(这里可以把它理解为一个工具类,名字不重要)会把所有的枚举常量转换为一个Name对象,然后将其存储在Name对象的内部类Table中,这时候Name对象就与Token序列建立了一个映射关系;每当我们传进来一个源码字符集合的Name对象的时候,词法解析器就会先找到Name类的内部类Table,在里面获取到对应的Token对象后,将源码字符集合与对应的Token对象的关系存储在Keywords类的Token key[]数组中;我们可以用一张图来表示这个过程,如下:

1.2.2  语法解析:
语法解析的作用就是把匹配得到的Token序列整合成一个语法树;

1.2.3  语义分析:
语义分析就是将语法分析产生的语法树进一步完善,例如给类 添加的默认构造函数,检查变量在使用前是否初始化,将一些常量进行合并处理,检查操作变量类型是否匹配,检查所有的操作语句是否可达,检查异常是否已经捕获或者抛出,解除java语法糖,等。

1.2.4  生成字节码:
遍历语法树,生成最终的字节码。

Java虚拟机(JVM)

1、大家都知道Java是一门可以跨平台的语言,就是因为java源代码的编译结果字节码文件,而字节码文件是在JVM上面运行的,JVM是java技术的真正核心,俗话说得好,一个人对java理解的深度取决于他对JVM的理解深度,由此可以看出,JVM是我们的重中之重;
2、字节码文件加载到JVM中又是经历了一个怎样的过程呢,那我们就读一下下面的这一篇文章吧!
畅谈类加载的过程

 

3、java王国的国王想知道JVM这个小伙是怎么做的这么优秀的,谁先彻底研究清除,重重有赏,无数谋士纷纷前往,但又有几个真的了解了这个城府如此之深的小伙呢;但我们不能放弃,下面就让我们一起去剖析一下JVM到底是一个什么东西,他是如何做到外交部长交给他的任务的:
绑架JVM

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326485449&siteId=291194637