这是一个程序员的电脑硬盘,在一个叫做“learning”的目录下有两个小程序,一个叫Hello.java,一个叫hello.c。hello.java自视甚高,有点看不起老派的hello.c,经常称他为“C老头”。这个hello.c也看不起这个“嚣张”的java程序,还给他起了个外号:“Java小子”。但是这个目录中没有其他人。每天晚上,主人入睡后,都会有无边的黑暗和无尽的孤独。C老头和Java小子虽然互不喜欢,但还是要聊聊解闷。“C老头,听说你的C语言诞生之初也是以便携着称的?”可移植性是Java最引以为豪的特性。一次编写到处运行可不是闹着玩的。他决定用自己的长处去攻击对方的短处。羞辱他。“哪里来的,我们比不上你的Java”没想到老C不跳坑,Java小子的招数都看不出来了。“那你为什么说移植性好?难道在Windows平台上开发的程序可以在Linux上运行?”爪哇小子不甘心,继续追。“我们指的是代码的可移植性,而不是程序的可移植性。比如我的hello.c可以在windows上编译运行,完全不修改代码也可以在linux上编译运行。“JavaKid我很奇怪,这到处都是编译编译,好像一点都不比自己差。他感到有些沮丧。斧头似乎下不去。但是转念一想,hello.c只是一个很简单的程序。它在Windows和Linux上都有它的编译器和标准库,所以肯定可以移植。如果使用系统平台的接口怎么办?“如果调用Windows平台的API,比如创建线程,在Linux上怎么办?”《那我们在C语言中使用条件编译》 C老哥早就料到Java小子会问这个问题了。“哈哈,搞错了,好麻烦,源码里有那么多奇葩的#ifdef,程序员没累死。”Java小子终于抓住了把柄。“这已经很好了,在我们的C语言刚刚诞生的时候,但是在1970年代,还没有Java虚拟机这种东西,也没有可以屏蔽底层平台API的抽象层。你能硬着头皮吗?”-程序员?”C老头说话客观,Java小子的嚣张气焰顿时消了大半。“那为什么C语言不与时俱进,构建虚拟机呢?”Java小子是个异想天开的人。”这个你不懂,C语言天生就是做系统级编程的,就是贴近硬件,追求性能和效率,弄个虚拟机,怎么直接操作内存呢?硬件?对了,我们可以用指针直接操作内存,效率极高,你的Java就不行了。“Java当然没有指针,那玩意儿太容易出错,容易出现漏洞。我们的父亲JamesGosling禁止我们直接操作内存。”独立执行,你就变成了Hello.Worm。”爪哇老头不动声色,开始组织反击。Java什么也没说。”还有,我的hello.exe一旦运行起来,它就是一个独立的进程,拥有独立的地址空间,由CPU独立调度;而你的Hello.class什么都不是,Java虚拟机(java.exe)就是一个进程。Hello.class加载后,在本进程中只能作为线程运行,生存空间是方法区,堆.....这个境界太远了。江尚老爷子火爆,老爷子C要命。“等等,林克,你刚刚说了什么?这到底是什么东西?” JavaKid抓起一根吸管。”你不懂链接?太老套了,去?的第七章。简单的说,就是给这个符号的地址绑定一个符号。“我只看了《深入理解Java虚拟机》,没看到任何链接,你的定义太抽象了,没人看得懂!”C老头心里很鄙视这个Java小子,见识实在是肤浅,还打算举个例子解释一下什么是链接。“你知道编译是如何工作的吗?”C老头打算另辟蹊径向Java解释。“那我肯定知道,我的Hello.java编译后会变成Hello.class”“我们的C语言程序,经过预处理、编译、汇编等步骤,可以变成一个叫做‘目标文件’的东西”“假设我的hello.c程序调用cal.c中的函数add:"hello.c:cal.c:"然后会生成两个目标文件,hello.o和cal.o。Java小子问:“你的hello.o不能执行吗?”“肯定是不执行的,你看add函数的定义在目标文件cal.o里,根本不在我的hello.o里!怎么执行呢?所以编译器要记录这样的东西在hello.o:hello.o中需要调用add函数,但是这个函数的实际地址不在这个文件中,链接的时候需要找到实际地址替换掉!替换过程是一个重定位过程,只有这一步完成后才能执行。”Java小哥说:“不行,假设我在另一个类Calculator.java中也调用了add方法,我们编译后会生成两个class文件。。”“你会的肯定是做链接的,但是这个链接不是在编译时做的,而是在运行时做的。当Hello.class加载到你的Java虚拟机中运行时,你会发现有一条指令调用Calculator的add方法。这时候,需要加载Claculator.class,找到add方法调用执行,这也是链接,不过是j只是运行时的动态链接。”老C作了总结性的陈述。Java小子现在明白C老头说的那个链接的意思了:Bindasymbol(add函数的名字)和这个symbol的地址(add函数的真实地址,这里有add的指令)功能)。“这老夫的实力不俗。”Java小子忍不住对C老头表示敬意,决定从明天开始不再叫他C老头,叫他老师,向他请教。眼看着天快亮了,两人互道了晚安。第二天半夜,Java小哥兴奋的向C君请教,不过你好,我是Python,我是新来的,请多多关照。”“你知道你好在哪里吗?对了,hello.c被删了。”【本文为专栏作家“刘欣”原创稿件,转载请通过作者微信获得授权公众号编码】点此查看作者更多好文
