1、深入理解JVM类加载机制

总体运行流程

image.png

类加载流程

image.png
首先,类被编译后生成类文件,c++创建的引导类加载器调用launcher类的方法创建java的类加载器,此时即可进入类加载的流程。

  • 验证 : 每一个类文件的字节码文件开头都会有sun公司的标识符,并且所有的字节码都是有规律的不可破坏。
  • 准备: 将类体重的静态属性赋予默认值,常量除外。
  • 解析: 这一步比较复杂,是静态链接的过程,即符号引用变成直接引用,一个类被加载进jvm内存后,由原来的字符引用替换成该属性的直接内存地址
  • 初始化: 将对应的静态属性赋值,替换掉默认值。

类加载机制本质就是将字节码文件加载进jvm内存中然后进行执行,而且大部分类都是懒加载的,即只有在运行时才会动态链接,进行加载。

一个对象在定义的时候是不会执行类加载流程的,只有当调用构造方法或者反射获取该类的类文件时,才会类加载。

双亲委派机制:
引导类加载器—》扩展类加载器—》引用类加载器
image.png

由c++实现会生成一个java虚拟机启动器,Launcher类,会调用自己的构造方法生成ext类加载器和app类加载器。
app加载器会尝试加载所有类文件,但是首先都会尝试让父类去加载,父类也会尝试让启动类加载器去加载,从而实现类的安全性,以防篡改核心代码。
沙箱安全机制。

TIP : tomcat已经重写了一个自己的类加载器,来解决不同的应用程序加载不同的web程序,那么最关键的是打破双亲委派机制,每个jar包都会有一个自己的类加载器,加载jar包只自己加载,但是不会委托加载。

源码实现

#

2、JVM内存模型

image.png
栈空闲其实就是线程栈,每一个线程在执行的时候都会从栈中获取一块空间来存放自己的变量,即使是相同的代码变量的内存地址也是不同的。
在栈中只要启动了一个线程即会分配空间,而创建一个thread也即是分为一个栈空间来供该线程使用,线程与线程之间不可见。
在整个jvm中,一个函数会对应一个栈帧对应空间存放局部变量。