您的位置:首页 > 编程语言 > C语言/C++

C\C++ 程序员从零开始学习Android - 个人学习笔记(二) - java基础 - 从源代码到运行

2012-01-20 17:26 991 查看
hello world 的起源到终结:

先大体写一下,以后会细化。

1,源代码

  C\C++:

main函数作为入口,将从main函数开始运行

  java:

包含static void main(String[] args)的类作为主类,将从指定为主类的main函数开始运行,

2,编译

  C\C++:

通过编译器(cl、gcc、armcc等),src -> 预处理 -> .s(汇编代码) -> .o(目标文件),每个.C文件生成一个对应的.o文件,.o文件包含二进制数据、本地机器码和其他一些用于链接及调试的结构性数据。

  java:

通过编译器(javac), src -> .class(二进制类文件),每个类生成一个对应的.class文件,.class文件包含类信息(类名、方法名等等)、二进制数据、字节码等(可以看做一种平台无关的中间代码,java虚拟机解释执行字节码)。注:这里不涉及JIT(Just In Time 即时代码生成器,将java字节码编译成本地机器码的编译器)。

3,链接

  C\C++:

通过链接器(ld、armlink等)链接.o文件以及其所用到的函数(printf\cout)所属的(标准)函数\类库(stdc.lib、STL),进行符号解析及重定位,生成平台相关的二进制可执行文件(PE、ELF等文件格式,扩展名一般为.exe、.a、.bin、.axf等)。

  java:

不同于C\C++,java的链接发生在加载运行时,而不是在此之前;每个class文件都是一个可加载运行的模块。

4,加载&运行

  C\C++:

双击.exe,或者shell运行相应命令,即触发一个加载运行的动作: 通过加载器,分配内存,解析二进制可执行文件,将其中的数据(.data、.bss或RW、ZI等平台相关的段)、代码(.text或RO等平台相关的段)拷贝到指定的内存映像中,并进行相应的初始化。最后设置PC寄存器,跳转到main函数开始执行本地机器码。

  java:

在命令行(shell)中运行命令:java mainclass,启动虚拟机,以mainclass作为主类,通过虚拟机的启动类加载器(初始类加载器、引导类加载器)进行加载运行:

  首先加载类(解析.class文件,从中获取类信息)。

  然后进行链接,分为三步:

验证 - 保证类或接口的二进制表示是正确的;

准备 - 为类的静态域分配内存并用默认值来进行初始化;

解析 - 类似于C\C++中的符号解析+重定位,将符号引用解析成直接引用,在此过程中可能会导致对引用符号所属的新类的加载,这步可以延迟进行,即执行到相关符号的字节码时再执行。

  然后进行初始化(类初始化,不是实例初始化,初始化静态类变量(域)):如果此类存在直接父类,并且父类没有初始化,则先初始化父类;包括域初始化和静态块初始化,按java代码中的初始化语句顺序进行。

  最后设置PC(虚拟机PC,非硬件寄存器),跳转到主类的main函数开始执行字节码,字节码的执行过程是一个解释的过程,由虚拟机(解释器)将字节码翻译成本地机器码执行。

5,消亡

  C\C++:

一般在一个进程中运行程序,运行结束后由操作系统回收此进程,释放相关资源。

  java:

虚拟机的一个实例运行于操作系统的一个进程中,其内部有两种线程(一般虚拟机自己实现,没有直接使用OS的线程;但Android的虚拟机直接使用了linux的线程 - 或者称之为轻进程):守护(Daemon)线程和非守护线程,前者是虚拟机自用线程(垃圾回收等),后者是用户代码创建的线程,hello world便运行于非守护线程中;只要有任何的非守护线程在运行,虚拟机便一直存活,当所有的非守护线程都结束后,虚拟机实例就自动退出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐