JVM虚拟机class文件结构和加载过程
java语言被称为跨平台的语言,而JVM可以被称之为跨语言的平台。很多语言如java,scala,kotlin,groovy,clojure,jython,jruby等等这些都可以编译成class文件。所以可以说JVM与java无关,任何语言只要可以编译成class文件就可以在jvm上运行。
想要了解JVM那么首先需要了解java从编码到执行的过程。首先如我们前面所说xxx.java要经过javac编译成.class。然后通过ClassLoader load到内存,然后虚拟机还会把java类库也load到内存。因为java是编译和解释混合执行,接下来会分析热点代码编译执行,普通代码解释执行最后通过执行引擎执行写入硬件。可以用一张图来描述
class文件是JVM运行的基础,那么先让我们来熟悉一下class文件的结构通常我们看到的是class文件16进制的格式我们来分析一下他的结构
从版本号到常量池个数到常量池,代表方法接口class类名等。
接下来我们要了解一下JVM加载类的过程。整个过程分为三个Loading、Linking、Initializing
Linking又分为Verification,Preparation,Resolusion
1.loading
loading的过程是采用双亲委派机制。当需要加载一个class的时候当前类的Classloader会查询是否加载过,如果没有会委托父加载器检查(注意父加载器不是父类的加载器他们没有继承关系)。一直到最上面的Bootstrap如果没有在往下委派加载一直到能够把类加载进来。如果到最后也没能完成加载则抛出classNotfound异常
加载器的层次关系如下
双亲委派机制是Classloader的loadclass方法写好的逻辑。如果我们想要用自定义的classloader则需要重写findClass方法。而有些时候比如tomcat的热部署则需要打破双亲委派机制这时候我们就需要重写loadclass方法了。
2.Linking
进入到linking阶段,首先要对class文件进行校验Verification。如果不符合JVM规范则会在这个阶段返回异常。然后通过Preparation阶段将静态变量赋默认值。Resolusion阶段将符号引用解析为具体地址引用。
3.Initializing最后Initializing则将静态变量赋初始值也就是初始化的过程。