java 生成文件_一个.Java文件从生成并在JVM中运行都经历了什么?

从广义上来讲,java文件从诞生都会经历以下过程:

编译-->将编译好的类加载到虚拟机中-->使用

一、编译

这个过程是把人能看懂而机器看不懂的程序代码通过javac编译器编译后生成机器能看懂的字节码文件!

用官方点的话说就是把一种语言规范转化为另一种语言规范!在这个转化过程中,编译器会做什么事情呢?

0711712469f016fb8eb4525865afb843.png

上面一张图可以说明这个过程:

1)词法分析:读取源代码,一个字节一个字节的读进来,找出这些词法中我们定义的语言关键词如:if、else、while等,识别这些关键词的合法与否.

词法分析结果:从源代码中找出了一些规范化的token流,就像人类语言中,给你一句话你要分辨出哪些是一个词语,哪些是标点符号,哪些是动词,哪些是名词。

2)语法分析:对词法分析中得到的token流进行语法分析,这一步就是检查这些关键词组合在一起是不是符合Java语言规范。例如if的后面是不是紧跟着一个布尔型判断表达式。

语法分析结果:形成一个符合Java语言规定的抽象语法树,抽象语法树是一个结构化的语法表达形式,它的作用是把语言的主要词法用一个结构化的形式组织在一起。这棵语法树可以被后面按照新的规则再重新组织。

3)语义分析:语法分析完成之后也就不存在语法问题了,语义分析的主要工作就是把一些难懂的,复杂的语法转化成更简单的语法。就如难懂的文言文转化为大家都懂的百话文,或者是注释一下一些不懂的成语。

语义分析结果:将复杂的语法转化为简单的语法,对应到Java就是将foreach转化为for循环,还有一些注释等。最后生成一棵抽象的语法树,这棵语法树也就更接近目标语言的语法规则。

4)字节码生成:将会根据经过注释的抽象语法树生成字节码,也就是将一个数据结构转化为另外一个数据结构。就像将所有的中文词语翻译成英文单词后按照英文语法组装文英文语句。代码生成器的结果就是生成符合java虚拟机规范的字节码。这个过程中的需要的组件如下图2所示:

646e8f7165702dad4c21bf6efcc3fc77.png

二、将编译好的类通过类加载器加载到虚拟机内存中

在这个过程中JVM使用类加载器通过全盘负责制或双亲委派机制将class文件加载到方法区中(在JDK1.8之后则是加载到元空间,方法区的特点是线程共享,用来存储类的信息,常量,静态变量,以及即时编译器编译好的热点代码等),那什么又是全盘负责制和双亲委派机制呢 ?

全盘负责机制:

当一个类运行时,可能有其他的类,这时由应用类加载器委托给扩展类加载器是否加载这些类,扩展类加载器再次向上委托引导类加载器是否加载这些类,引导类加载器判断后将有的类进行加载向内存中返回class对象后,再由扩展类加载器中有的类进行加载返回class对象,剩下全部有应用类加载器进行加载.

双亲委派机制:

就是将请求加载的类委托给父类的加载器去加载,如果父类的类加载器无法完成加载,才会去调用子类的类加载器去实现加载.这样做的目的是防止多个子类加载各自父类,导致父类重复的现象发生!

类加载器:

Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:

  • 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
  • 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
  • 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。

除了系统提供的类加载器以外,开发人员可以通过继承 java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求。

除了引导类加载器之外,所有的类加载器都有一个父类加载器。通过getParent()方法可以得到。对于系统提供的类加载器来说,系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器;对于开发人员编写的类加载器来说,其父类加载器是加载此类加载器 Java 类的类加载器。因为类加载器 Java 类如同其它的 Java 类一样,也是要由类加载器来加载的。一般来说,开发人员编写的类加载器的父类加载器是系统类加载器。类加载器通过这种方式组织起来,形成树状结构。树的根节点就是引导类加载器。图 1中给出了一个典型的类加载器树状组织结构示意图,其中的箭头指向的是父类加载器。

图 1. 类加载器树状组织结构示意图

ef6cb2b4f311e32ab196bca97cad700d.png

如果出现自定义的类名与JDK中的类名重复会发生什么 ?

由于全盘负责制自定义的类没有机会被加载

三、验证

四、准备

五、解析

六、初始化

七、使用

  1. 类中的分支,循环,跳转,异常处理,线程恢复通过程序计数器去完成,而程序计数器是jvm中唯一不会发生OOM的内存区域;
  2. 类中方法的执行则是通过在虚拟机栈中新建栈帧的入栈和出栈去实现,如果玩脱了递归,那么极易发生StactOverflowError的错误;
  3. 如果有本地方法(native方法)需要执行,则需要在本地方法栈中去执行.

、卸载

卸载不再使用的类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值