浅聊什么是语言自举
高级语言都是需要进行编译的,编译就是把高级语言翻译为机器指令。
就算是Java也需要编译,这里指的编译不是javac,而是jit编译器,javac负责把java代码编译为JVM字节码,jit编译器负责把字节码指令翻译为机器指令。
我们知道jit编译器是用c++开发的,那么我们能不能用Java语言开发一个编译器,然后通过它能够把Java代码直接编译成为机器指令呢?
肯定是可以的,就像C语言、Go语言一样,它们的编译器都是用自己的语言实现的。
能用本语言实现的编译器对本语言进行编译,这就是语言自举。
编译就是把一个用高级语言写的字符串,编译成为机器指令的字符串,这个功能基本上任何一个语言都能实现。
在Java中,GraalVM其实就完成了这个功能,GraalVM就是用Java开发的,同时它又能把Java代码编译成为机器指令。
这就有点像是,先有鸡还是先有蛋的问题了。
比如GraalVM,它是用Java语言开发的,相当于就是一个Java程序,可是它要执行编译Java代码的的话,不得自己先编译完才能执行吗?
也就是,Java编译器为了能编译Java代码,自己得先编译。
可是问题就是,这个编译器自己该怎么被编译呢?
这就是语言自举中要解决的问题。
通常,这个编译器的第一个版本不会是本语言实现的,而是通过其他语言。
比如我先用C++写一个Java编译器,记做CJava编译器,然后就可以用CJava编译器编译Java代码了,然后我又用Java代码写一个Java编译器项目,就可以利用CJava编译器编译这个项目,得到另外一个Java编译器了,而后续我们只需要用这个Java编译器就可以编译Java代码了。
这样就完成了语言自举。
当然,如果Java语言语法上有升级,对应的编译器也要升级,因为之前老版本的编译器可能编译不了新的语法,这个时候可能仍然得借助外力,也就是用另外一门语言来编译新的语法得对应的机器指令,比如C++。
知乎上有一个点赞不多,但是我觉得很好的比喻:
你是一个铁匠,专门给木匠提供生产工具的铁匠。
有一天你觉得你目前的工具制造工艺精度太低、效率不够高,于是你决定发明机床替代打铁和手工制作木制零件。
你手工用木头和铁制作了一个简单粗糙的手动机床。
有了这台机床之后你给木匠制作工具的效率明显提高了。但是用了一段时间之后,你发现这台机床的设计还是有一些不足,于是你决定开发第二版机床。
把设计图画好之后你开始动手了。这次你决定不用打铁削木头的方式制造第二版机床,而是用已经制作好的第一版机床制作大部分第二版机床的零件,只有小部分用第一代机床制作不出来的零件你手工制作。
第二代机床制作好之后你越用越顺手,越来越多的木匠开始用你用机床生产的工具。为了提升效率你决定开发第三代机床。
因为第二代机床的设计比第一代机床更完善,你发现生产第三代机床的所有零件都可以直接用第二代机床制作。于是你用第二代机床生产了第三代机床。
恭喜,你达成了机床自举。
今天初二,简单聊聊,要去拜年了,祝大家新年快乐,不想错过更多干货内容,关注公众号:Hoeller。
转载自:https://juejin.cn/post/7191694448228007996