C和Java的程序执行过程

前言

今天听一个师兄聊起他面试的经历,面试官问的第一个问题就是程序在main函数之前都进行写什么过程,他说他当 时答得不好,我自己想了想,虽然大致的能说上一些,但是感觉还是不太清晰,今天来总结一下。

C语言

由于机器只能认识二进制文件,所以用高级语言写成的程序必须得需要转换成为二进制磁盘文件,才能被机器执行 所以在main函数执行之前,就是一个文件的转换过程,如下:

  • 预处理

去掉程序中的’#‘号开头的命令,如:

    `#include<stdio.h>`   将库文件stdio.h直接插入源文件中

    `#define PI 3.14`     将define定义的常量直接替换

    `#if #else`           等条件编译处理

这时候得到的c程序一般以.i为扩展名

  • 编译

即将.i文件转化成汇编语言程序,汇编语言程序与机器语言程序就比较接近了,这时候的程序以.s为扩展名

  • 汇编

编辑器将汇编程序转化为二进制文件,即可重定位的目标程序(机器码),这个时候程序才被转化为二进制,之前 的两个阶段程序还是文本格式的。此时的程序文件以.o为扩展名

  • 链接

将各个二进制文件整合为目标可执行程序,如printf函数,这是标准c库的函数,存在于一个名为printf.o的单独 编译好的目标文件中,链接器将其连接到目标文件中,生成可执行文件,它由源程序的名称来标识。这个时候的 程序是可以被加载到内存中执行的。

最后就是执行程序了,shell接收到用户的输入命令后,将用户的键入存放到寄存器中,一旦用户的键入结束,shell 将指定的代码和数据加载到内存,这么时候就开始执行main函数了。

java

由于c语言是过程性语言,所以在运行之前执行的有些繁琐,java作为一门解释型语言,它在运行之前的做的工作 显然没有c语言那么多。但是java也有一个编译的过程,也可将其称为半解释型语言,其过程为:

  • 编译

编译会将.java源文件转换成为.class文件,这是一个字节码文件,如果用编译器打开会是一堆乱码,java程序的 执行速度不如c语言的原因部分是因为java程序和二进制程序中间需要转换成.class字节码文件。

.class文件主要分为两部分:

    常量池       类名,成员变量名和方法引用   
    方法字节码   各个方法的字节码

可以通过.class文件的反编译来验证。不过在编译的时候,会先去找依赖的类,再编译当前类。

  • 运行 java程序的运行过程有两个阶段:

    • 加载 即类的.class字节码被加载到内存中,一般第一次使用的时候才会加载(惰性加载),这时候会为每个 类创建一个Class对象。
    • 初始化 由可分为静态初始化和一般初始化,静态初始化在类加载时完成,一般静态初始化自会在Class对象首 次加载的时候进行一次,当创建一个对象时,首先会在堆上分配足够的存储空间,这时候这块存储空间会被清零, 即对象中的所有基本数据类型都会被设置成0,然后再执行字段定义处的初始化动作,最后执行构造器。

在java程序运行时最重要的是JVM,只有真正了解了JVM,才能对java程序的运行过程有个更深刻的了解。



Previous     Next
zhing /
Published under (CC) BY-NC-SA in categories java  tagged with java