轻量级前端框架助力开发者提升项目效率与性能
594
2022-11-03
windows系统使用c++实现一个小型jvm(三)------------jvm的启动细节2
这篇文章接着上午记录下。
1.标准输入输出流是怎么来的?
在写java程序的时候,我们经常输出控制台信息,调用的如下代码: System.out.Println(); 在这里,我将解释这个的由来。
jvm在初始化时,必须先加载FileDescriptor,FileDescriptor有三个静态成员:
它们会调用本地FileDescriptor的SetI方法:
void JVM_FD_Set(list
windows中,每个程序的标准输入输出流和错误流,为当前程序的控制台。 这里实际上就是控制台程序的句柄给设置到相应的对象中。 之后再初始化System的时候,会有如下的代码片段:
而实际上这个setIn0,setOut0,setErr0,就是将输入输出流句柄,给设置到 System.in,或者System.out,System.error属性上去,其代码如下:
void JVM_SetOut0(list
另外,从这个流程中,我想起来大概两年前写 看java源码的 流 部分的时候,曾经总结过,说: java中真正更够读写的就两个流,一个是FileInputStream/FileOutputStream ,另一个是ArrayIntputStream/ArrayOutputStream。 知识诚不欺我呀哈哈哈哈。
2.java的双亲类加载机制:
说到这个古老的话题,那可得追溯到我写文章开始。 那一年春节,我决定看看源码,一上来就猛的 想把那个双亲加载机制给搞明白。 事实上,一直没怎么搞明白,唯一的作用是给了自己学习的动力。 但是今天我想借着这个机会,是可以完全搞懂的。
上午说到,jvm在加载客户类之前,会启动一个LauncherHelper类,代码如下:
BytecodeEngine::initial_client(launcher_helper_klass, *this); Method *load_main_method = launcher_helper_klass->get_this_class_method(L"checkAndLoadMain:(ZILjava/lang/String;)Ljava/lang/Class;"); // new a String. wstring ss = automan_jvm::main_class_name(); InstanceOop *main_klass = (InstanceOop *)java_lang_string::intern(automan_jvm::main_class_name()); this->vm_stack.push_back(StackFrame(load_main_method, nullptr, nullptr, {new IntOop(true), new IntOop(1), main_klass}, this)); //todo: 到这里应该是java层面的类加载器开始生效!!! MirrorOop *main_class_mirror = (MirrorOop *)this->execute();
接着去看看 checkAndLoadMain方法:
之后通过ClassLoader的loadClass方法,通过查找虚拟表,调用Launcher的AppClassLoader的loadClass方法,再调用之前,将会首先进行AppClassClassloader的初始化(这个初始化过程蛮复杂的):
花了较多的精力去看这块的源码,主要原因基于以下几点:
1.windows中由于文件系统路径分隔符的原因,我在调试时就遇到了一个坑,即我明明需要使用 文件系统去加载,但是它却使用了JarLoader去加载。 现在回过头来,知道了其原因: 首先在LauncherHelper中会根据模式选择加载器,其次会判断java.class.path下面的所有配置路径,如果为文件夹,则会匹配为 fileLoader,如果为文件,则会使用默认的loader,而实际上默认的loader,其最终采用的还是Jarloader的方式加载的。(我的问题就出在这!)。
2.AppClassLoader与ExtClassLoader都继承自URLClasspath,因此必须弄明白URLClasspath是在什么时机初始化的,以及相应的参数都是什么。 关于URLClasspath的作用,网上帖子挺多。 它的几个关键方法: loadClass,findClass,defineClass 可以用于验证双亲委派机制的运行流程。
我在调试时,分别给loadClass 和 defineClass添加了锚点, 最终实际上是可以印证双亲委派模型的。 由于当时未截图,因此这里就不再继续操作了。(因为这个过程实在是有些痛苦~,感兴趣的小伙伴可以亲自调试一下)。
另外强调一点就是,以前没有认识到URLClassLoader在java中的重要性,以及URLClassLoader与URLClasspath的关系,这是一个十分有趣的问题。
此外,在AppclassLoader加载类的过程中,它的流将会以匿名内部类的形式给出:
就到这吧,原计划写的很详细的,但是真写了太细了吧,速度太慢,自己又是个急性子。 whatever,后面赶紧把gc写了要开始投入新一轮的学习,同时得计划找工作了55555。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~