你所不知道的Hello World背后的原理

据说阿里某程序员对书法十分感兴趣,退休后决定在这方面有所建树。于是花重金购买了上等的文房四宝。

一日,饭后突生雅兴,一番磨墨拟纸,并点上了上好的檀香,颇有王羲之风范,又具颜真卿气势,定神片刻,泼墨挥毫,郑重地写下一行字:hello world。

当然了,这是个专属程序员的段子哈哈哈。

那么问题来了,写了这么久的Hello World,大家确定自己了解自己写的东西背后是什么原理吗?(o???)

【给出2分钟,该知识点涉及到了Java程序执行流程,包括编译、加载和执行,你是否能够理清呢?】

接下来进入严肃时间 (@ ̄ー ̄@)

与众不同的Hello World

public class Main {

    private static String word = "Hello World!";

    public static void main(String[] args) {
        new Main().say();
    }

    private void say() {
        System.out.println(word);
    }
}

整个代码的执行过程可以分为三个阶段:

  • 代码编译
  • 类加载
  • 类执行

代码编译

代码编译的作用就是将我们编写的 Main.java文件转化为Main.class文件,.class在这里又被称为字节码文件,打开就是一堆的火星文【反正就是看不懂】,在这里我们可以将编译的过程看作生产JVM原料的过程,使用的工具就是jdk提供的工具javac。
大致流程如下:

  • 词法分析,即将源代码的字符流转变为Token集的过程。白话文描述下,就是在我们实际编程中,单个字符是最小单位,而实际上在编程过程中,标记才是最小单位,如关键字、变量名、字面量、运算符等都可以成为Token,貌似还是有点蒙蔽,举个例子(>﹏<),比如整型int在我们编程中它就是三个字符组成的,就是i、n、t 三个字符,而在编译过程中它就是一个Token,不可拆分。

这个过程对我们来说其实是完全屏蔽的,但是实际上它是现代经典编译原理的
套路,词法分析也是为了给后面编译做准备的】

  • 语法分析,通过词法分析拿到Token集后,下一步就是构建抽象语法树了,所谓的抽象语法树其实就是一种用来描述程序代码语法结构的树形表示方式,其中语法树的每一个节点都代表着程序代码中的一个语法结构,如包、类型、修饰符、运算符等。

在我们眼中,Main.java已经可以清晰理解到底写的是什么东西了,但是对于JVM来说还是一脸懵逼的,所以才需要构建成语法树,在这一步后就不会再对源码文件进行操作了,后续的操作都建立在抽象语法树上

  • 填充符号表,符号表是由一组符号地址和符号信息构成的表格,这个表格在编译的不同阶段都会被用到,如在目标代码生成阶段,会对符号名进行地址分配,而符号表就是地址分配的依据。
  • 语义分析,语义分析阶段也可以说是语义检测阶段,上面说到语法分析会构建一棵语法树,那么这棵语法树是否是正确合理的,就由语义分析来做了,语义分析会通过标注检查和数据及控制流分析检查两步入手,在生成字节码的最后一步信息把关。
  • 字节码生成,这是javac编译过程的最后一个阶段了,字节码生成阶段并不只是简简单单的将前面各个步骤生成的信息转化成字节码然后放入磁盘中,还进行了少量的代码添加和转换工作,如我们自己重载的构造函数。

编译期到这里就结束了,那么由谁来将这些原料传输给JVM虚拟机呢?这个时候就要看看类加载的过程了。

类加载

类加载简单来说就是将由类加载器将编译后的字节码文件【Main.class】加载到虚拟机中
,那么自然而然的,要先介绍下四种类加载器

说说四种类加载器

可以从上图中看出,类加载器可以分为四种,而第四种是由我们自己实现的,那么其他三种由JVM提供的类加载在我们启动该Main程序的过程中起到了什么作用呢?

首先说说启动类加载器 Bootstrap ClassLoader ,启动类加载器的作用主要是加载 %JAVA_HOME%\jre\lib\rt.jar 类库,将其加载到虚拟机内存中,那么rt.jar类库到底有什么作用呢?rt.jar下包含了Java的基础类库,也就是Java doc里面看到的所有的类的class文件,感兴趣的朋友可以自己打开目录看下。

其次是扩展类加载器 Extension ClassLoader ,扩展类加载器的作用主要是负责加载JAVA_HOME\jre\lib\ext目录下的所有类库,主要是载入扩展包。

再者是系统类加载器 Application ClassLoader, 也称之为应用程序类加载器,负责加载用户类路径(也就是我们配置的CLASSPATH)上所指定的类库,是应用程序中默认的类加载。

看完以上三个类加载器的简单描述过程,是不是有种终于知道了我们配置的jdk环境的最终作用了吧,是的,就是让类加载器识别到后加载各种类库。

那么问题来了?是哪个类加载器加载了我们的Hello World程序呢?是的,就是应用程序中默认的类加载器 Application ClassLoader。

知道了类加载器后,那接下来总要了解下类加载器怎么加载的吧?

说说类加载的过程

网上找了张图片,简单明了。虽说是简单明了,不过确实异常重要的,因为是面试热点(????)

加载

其实就是上文说到的系统类加载器 Application ClassLoader将编译后的Main.class文件加载到内存中。

【思考】抛出个问题,所谓的加载到内存中,我们都知道JVM把内存分成了几大模块,那么请问是加载到哪个模块中?热点面试题,答案见文末

链接

链接中包含了三部曲,总的作用就是负责将Main.class的二进制数据合并到JRE中。

关于三部曲,其实很好理解;

首先是验证阶段,类加载器将二进制字节流加载到虚拟机中,肯定是需要进行验证的,避免危害虚拟机自身安全,而这也是验证阶段存在的价值;

接下来是准备阶段,准备阶段是正式为类变量分配内存并且设置类变量默认值的地方,比如上面HelloWorld程序中的

private static String word = "Hello World!";

注意我描述的第一个是类变量,也就是static所描述的变量,其次是默认值,也就是上面的word的默认值null,如果是数字则为0。

最后是解析阶段,解析阶段的作用主要是将常量池内的符号引用替换为直接引用的过程,解析阶段其实有点难理解,至少是比上面的两个阶段要难理解的,我这里尽量直白点;

所谓的符号引用指的是包含了类的信息、方法名、方法参数等信息的字符串,而当第一次运行时,JVM会根据这行字符串去检索到对应的方法入口,而为了下次不用再做同样的检索,在第一次运行的时候就会将符号引用替换成直接引用,这样后面就可以省去一定的消耗了;这里的直接引用其实就是指偏移量,虚拟机可以通过偏移量直接找到方法入口,不再需要做检索了。

初始化
终于来到初始化阶段了,上面我们有说到word默认值是null,是系统赋的默认值,而在初始化阶段,则是根据我们人为的初始化类变量和其他资源,比如上面的word则被我初始化成了"Hello World!"。

类执行

上面说到Main.class被加载到了Java虚拟机内存中,那么接下来便是执行的过程了。那么由谁来执行这一过程呢?

实际上,一个Java虚拟机在运行的时候可以划分为三个子系统:

  • 类加载子系统
  • 执行引擎子系统
  • 垃圾收集子系统

很明显、很清晰,图中的类加载子系统在上面已经谈了,执行引擎子系统就是负责执行这一部分的,那么过程是怎么样的呢?

其实很简单,执行引擎会把字节码转换为机器码【what?竟然还要转换。拜托<(ˉ^ˉ)>,字节码是被JVM识别的语言,字节码才是最终被操作系统识别的语言】

然后操作系统才可以真正调用,很多学或者做Java的人都听过JIT,但是都不知道具体是干嘛的,没错说的就是你。

这里终于可以解释下了,字节码转换成机器码的翻译工作使用的就是JIT(Just In Time)即时编译器(对热代码整段编译)和Java字节码解释器(一行一行解释字节码)来完成的。
这里给下JIT编译的工作流程:

JVM字节码 -> 机器无关优化 -> 中间代码 -> 机器相关优化 -> 中间代码 -> 寄存器分配器 -> 中间代码 -> 目标机器码生成器 -> 目标机器码

最后执行引擎会找到main()这个入口方法,并且执行其中的字节码指令。

【思考解惑】加载阶段完成后,虚拟机会将Main.class的二进制字节流按照虚拟机所需的格式存储在方法区之中,然后在内存中实例化一个java.lang.Class类的对象,作为程序访问方法区中的这些类型数据的外部接口,实例化后的java.lang.Class类的对象也是存放在方法区中的。

原文地址:https://blog.51cto.com/14295088/2415841

时间: 2024-10-20 18:10:17

你所不知道的Hello World背后的原理的相关文章

你所不知道的SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)

前言 本篇主要是上一篇文章的补充篇,上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和解决方法,可点击查看,我们此篇主要介绍的是SQL Server启动过程中关于用户数据库加载的流程,并且根据加载过程中所遇到的一系列问题提供解决方案. 其实SQL Server作为微软的一款优秀RDBMS,它启动的过程中,本身所带的那些系统库发生问题的情况相对还是很少的,我们在平常使用中,出问题的大部分集中于我们自己建立的用户数据库. 而且,相对于侧重面而言,其实我们更关注的是我们自己建立的用户数

Android中Context详解 ---- 你所不知道的Context

转载至 :http://blog.csdn.net/qinjuning 前言:本文是我读<Android内核剖析>第7章 后形成的读书笔记 ,在此向欲了解Android框架的书籍推荐此书. 大家好,  今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中 时刻的在与它打交道,例如:Service.BroadcastReceiver.Activity等都会利用到Context的相关方法 : 说它陌生,完全是 因为我们真正的不懂Context

Android中Context详解 ---- 你所不知道的Context (转载)

Android中Context详解 ---- 你所不知道的Context (转载) http://blog.csdn.net/qinjuning 大家好,  今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中 时刻的在与它打交道,例如:Service.BroadcastReceiver.Activity等都会利用到Context的相关方法 : 说它陌生,完全是 因为我们真正的不懂Context的原理.类结构关系.一个简单的问题是,一个应用

Android中Context详解 ---- 你所不知道的Context(转)

Android中Context详解 ---- 你所不知道的Context(转)                                              本文出处 :http://blog.csdn.net/qinjuning 前言:本文是我读<Android内核剖析>第7章 后形成的读书笔记 ,在此向欲了解Android框架的书籍推荐此书. 大家好,  今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中 时刻的在与它打

你所不知道的html5与html中的那些事(二)

文章简介: 关于html5相信大家早已经耳熟能详,但是他真正的意义在具体的开发中会有什么作用呢?相对于html,他又有怎样的新的定义与新理念在里面呢?为什么一些专家认为html5完全完成后,所有的工作都可以达到真正的云方式呢?这一系列的问题你是否已经想明白了呢? 本系列文章将为您一一解答你所不知道的关于html5与html中的那些事;具体会包括如:html5新的理念与想法,html5的新标签的用意与具体开发中场景应用,html5与css3的感情经历(用法搭配),包括html5的父亲html的一些

你所不知道的html5与html中的那些事(一)

分类: Web开发 文章简介: 关于html5相信大家早已经耳熟能详,但是他真正的意义在具体的开发中会有什么作用呢?相对于html,他又有怎样的新的定义与新理念在里面呢?为什么一些专家认为html5完全完成后,所有的工作都可以达到真正的云方式呢?这一系列的问题你是否已经想明白了呢? 本系列文章将为您一一解答你所不知道的关于html5与html中的那些事;具体会包括如:html5新的理念与想法,html5的新标签的用意与具体开发中场景应用,html5与css3的感情经历(用法搭配),包括html5

JavaScript你所不知道的困惑(2)

困惑一: var obj1 = new Object(); var obj2 = obj1; obj1.name = "阳光小强"; alert(obj2.name); //输出结果:阳光小强 JavaScript中的5个基本类型:Undefined.Null.Boolean.Number和String都是按值访问的,可以操作保存在变量中的实际的值,内存空间如下: var num1 = 5; var num2 = num1; 引用类型的值是保存在内存中的对象,JavaScript不允许

JavaScript你所不知道的困惑(1)

困惑一: 先看一个例子: function test(){ message = "hi"; } test(); alert(message); 会输出字符串"hi" 在函数内部使用var定义的变量是局部变量,省略var操作符的变量是全局变量. 困惑二: alert(undefined == null) 结果是"true" 我们知道在js中分为基本类型和引用类型,基本类型包括number.string.boolean.undefined.null.

你所不知道的html5与html中的那些事(四)——文本标签

文章简介: 关于html5相信大家早已经耳熟能详,但是他真正的意义在具体的开发中会有什么作用呢?相对于html,他又有怎样的新的定义与新理念在里面呢?为什么一些专家认为html5完全完成后,所有的工作都可以达到真正的云方式呢?这一系列的问题你是否已经想明白了呢? 本系列文章将为您一一解答你所不知道的关于html5与html中的那些事;具体会包括如:html5新的理念与想法,html5的新标签的用意与具体开发中场景应用,html5与css3的感情经历(用法搭配),包括html5的父亲html的一些