程序员想知道代码是怎样跑起来的

程序员使用Java语言实现累加求和的方法,将文件命名为Sample.java。java

public class Sample {
    public static void main(String[] args) {
        System.out.println(sum(10));
    }

    private static int sum(int n) {
        int res = 0;
        for (int i = 1; i < n; i++) {
            res += i;
        }
        return res;
    }
}

程序员不想直接点击运行,使用javac编译了Sample.java文件,能够看到Sample.java所在的目录下,生成了Sample.class文件。程序员

那要是汇编语言,具体步骤应该是怎样的啊?算法

不过,什么是汇编语言?汇编语言其实和硬件息息相关,也就是脱离不了实际的硬件环境,没法跨平台运行,由于汇编语言是人们用助记符表述CPU的动做。CPU结构不同,汇编语言调用的可能也不同。编程

那助记符是什么意思呢?汇编语言的每一行,表示对CPU的一个指令,其语法结构是操做码 + 操做数。固然也存在只有操做码,例如ret,表示将处理返回到函数的调用源。segmentfault

操做码是对CPU的指令,是动词,那操做码是数据,是存储在CPU的寄存器,是宾语。如mov a b; 表示将b的值赋值给a;add a b; 表示a同b的值相加,并将结果赋值给a。windows

那CPU是否是直接能懂这些助记符吗?固然不能。微信

咱们知道计算上全部的地址和数据都是由0和1组成的,将汇编语言的那些助记符写在文本文件上,进行编译的时候会调用本地计算机上的应用,名为masm.exe,是一个编译器。编程语言

将文本文件编译成目标文件,此时的目标文件成了机器语言,能够直接被本地的CPU所理解的,若是将这个目标文件由别的计算机的不一样系列CPU理解,那多是读不懂,就比如如咱们看不懂火星文。函数

那这个目标文件能够被本地CPU能够直接解析运行了吗?能够是能够,可是会直接被报错。优化

由于咱们仅有这一个目标文件,还不知道这个目标文件和系统的库文件哪些有关。因此,须要一个连接器,把相关的目标文件组合成一个能够在特定平台运行的可执行文件,以下图:

汇编语言

库文件名的后缀也是.O或 .OBJ。其中, .ASM .OBJ和 .EXE是在dos或windows系统下的文件, .S和 *.O是在以Linux内核的系统下的文件后缀名,不过Linux内核不靠文件后缀名来判断这是什么文件,通常靠文件属性来判断,可执行文件在Linux内核中没有后缀名,用ls命令显示这个文件是绿色就是可执行文件。

好了,若是是C/C++语言,它的编译过程应该是怎么样子的呢?

C语言编译器过程

预处理 是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些代码输出到一个“.i”文件中等待进一步处理;

转换 是把C/C++代码(好比上面的".i"文件)“翻译”成汇编代码;

编译 是将用助记符号表示的汇编语言翻译成符合必定格式的机器语言;

连接 是将汇编生成的OBJ文件、系统库的OBJ文件、库文件连接起来,最终生成能够在特定平台运行的可执行程序。

好了,写着写着忘记Java程序的正事了。

你们所说的Java,有两个层面意思,一个是做为编程语言的Java,另外一个是做为程序运行环境的Java。这就是Java的特殊所在,特殊就特殊在Java有Java虚拟机。

Java程序也须要编译,可是没有编译成机器语言,而是编译成字节码文件,而后在Java虚拟机用解释的方式执行字节码。

Java虚拟机

编译 是将Java源代码“翻译”为Java虚拟机可执行的字节码文件,保存到硬盘上;

加载 是将生成在内存上的字节码文件的副本,加载到Java虚拟机上;

Java虚拟机 加载后字节码后,执行方式有两种,一种是即时编译器,另外一种是字节码解释器,以下图:

Java虚拟机执行引擎

即时编译和解释执行的区别以下:

解释执行:将编译好的字节码一行一行地翻译为机器码执行。

编译执行:以方法为单位,将字节码一次性翻译为机器码后执行。

软件 是指Java虚拟机对于系统来讲,是一个应用,是用某个高级语言编写的应用。

固然,Java虚拟机对Java程序来讲,是一个运行的环境。咱们能够对比分析一下,把Java源代码想象成汇编语言源代码,字节码想象成本地CPU可执行的机器语言,Java虚拟机想象成本地CPU

因此这就是为何说Java是跨平台的,由于Java虚拟机是一个应用嘛。不过,不一样的系统,应用也是不一样的,因此系统不一样,Java虚拟机也是不一样的,可是字节码文件能够不变的,能够直接到其它不一样系统上的虚拟机解析执行的。

Java虚拟机运行的是字节码,字节码对Java来讲是十六进制;本地CPU执行的是机器码(机器语言),机器码对系统来讲是二进制。不过,字节码文件放在本地是0和1组成的,只是不能被本地系统解析执行,须要Java虚拟机即时编译或解释执行。

“百闻不如一见”,咱们看看*.class用记事本打开会是怎么样的。

记事本

这打开是乱码的啊?这是由于以class为后缀名的字节码文件在Java中保存的是十六进制,那咱们要看十六进制如何看呢?

咱们能够用Sublime Text 3打开字节码文件,但打开以前Sublime Text 3须要安装HexViewer插件,才能够看十六进制的,具体安装过程能够到网上搜索。打开以后,以下图所示:

Sublime Text 3

能够看到全部的数字都是十六进制的,接下来下一步就加载到Java虚拟机上去了,具体用即时编译的仍是解释执行的,或者在大项目中即时编译和解释执行都是能够共同打配合的,由于Java虚拟机在不一样的场景下用的是不一样的优化手段。
喜欢本文的朋友,微信搜索「算法无遗策」公众号,收看更多精彩的算法动画文章