本文出自:【InTheWorld的博客】 (欢迎留言、交流)
最近研究JVM已然走火入魔了,下午看了两个小时,终于看出了一点端倪。像我这样Java学个半吊子,就开始研究JVM源码的人实在是奇葩的存在!源码据说有50多万行,不过感觉也不是很多的样子。大概是linux源码看多了,觉得这hotspot并不是很大(坐等被虐出翔)。先记录一下成果吧!
首先,目录结构: 有os,cpu,os_cpu,share这几个目录,顾名思义,就是存放着不同特点的代码。os依赖的,cpu依赖的,共有的,还有os和cpu都依赖的。
其实,东西最多的是share目录下的东西。毕竟C++也是可移植的嘛!我跑马观花的看了看《深入Java虚拟机》,发现这本书的重点集中在字节码什么上面了。对于解释执行,执行引擎啥的基本没有讲,有点失望。不过也不怪他了,出书的时候hotspot还没开源呢!期望老哥可以研究hotspot之后,再写一本书。不过,今年也出了一本中国的hotspot的书,不知道质量如何,有机会看看。
我准备先从解释执行下手,我这原理强迫症真的已经是晚期了。直接到share/vm/interpreter下面去看看。找到了一个bytecodeInterpreter.cpp。然后成功地找到了while(1) (886行),while里就是一个超大switch语句。看到了这个东西,我一下就心安了,知道了hotspot使用的解释方法。但是这只是基本的,不是还有JIT吗?字节码是如何转化为机器码的呢?
反正我们知道有一部分字节码转化为机器码。最终,这个翻译工作被派到了asm目录下的assembler.cpp(它包含了assembler_x86.cpp中的内容)。assembler_x86里面的汇编器一个劲的调用emit_byte(*)什么的。这个函数明显是输出的,但是却没有指定输出位置。所以,我断定存在一个类似于全局缓存的东西。果然,asm目录下有一个codeBuffer.cpp。这个文件里具体完成了代码缓存的实现。汇编器什么都不用干,只需要将输出代码一个劲的往外扔就好了。emit_byte(),实现在了assembler.inline.cpp里面,代码非常的简单,就是往一个地址里写机器码。_code_pos是AbstractAssembler的成员变量。
下一步,准备去分析一下codeBuffer的代码是怎么被执行的?
(虽然这笔记现在看着有点幼稚,还是贴出来了,不怕出丑,好像也没人看的样子。。。)
后记:这是我当年写的第一篇JVM实现方面的博客。写得很差劲,本来不想转过来的,但是仔细想想,已经是快三年前的事情了,担心自己忘了当时的念头。希望自己能够坚持住,完成曾经想做的事情! 2017. 07. 08
发表评论