JVM-类加载

Java的生命周期

如下图Java的生命周期,大致可分为
 1. JAVA文件----Via JAVAC----------------->Class文件
 2. Class文件---Via ClassLoder------------>JMM
 3.1. JMM------Via JavaInterpreter------->执行
 3.2. JMM------Via Jit------------------->执行

这里写图片描述

类的生命周期

 1. 加载(Loading)至虚拟机内存
 2. 链接(Linking)----验证(Verification)
 3. 链接(Linking)----准备(Preparation)
 4. 链接(Linking)----解析(Resolution)
 5. 初始化(Initialization)---------类加载过程到此为止,6,7为虚拟机主导控制
 6. 使用(Using)
 7. 卸载(Unloading)出虚拟机内存

这里写图片描述

加载都干了些啥

 1. 通过一个类的全限定名来获取定义此类的二进制字节流
 2. 将字节流所代表的静态存储结构转化为方法区的运行时数据结构
 3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

补足说明:
  1.类的来源可以从 本地目录,ZIP包(JAR,WAR,EAR),网络传输,运行时计算生成(动态代理技术)
  2.JAVA中无处不是对象,正如上所说这个类也是一个对象,只不过比普通对象特殊些,称之为类对象,它所存放的地方也比较特殊,在1.7中存放与perm区,在1.8中存放在metaspace区,但跟heap区一样,是线程共享的,也存在OOM的可能。

验证


 1. 文件格式验证:是否符合Class文件格式的验证
 2. 元数据验证:对字节码描述的信息进行语义分析
 3. 字节码验证:通过数据流和控制流分析程序语义合乎逻辑
 4. 符号引用验证:讲符号引用转换为直接引用--->在解析阶段发生

准备

 1. 为类变量分配内存并设置类变量初始值
 补足说明:
 1.在这里分配内存的对象是被static修饰的类变量,而不是实例变量,实例变量将会在对象实例化时被分配到Heap中。
 2.初始值为0值,而非被赋予的值,但被static final修饰的值为被赋予的值
   对类变量的初始化在 后续的初始化阶段进行
 如:public static int value=123;--------->在准备阶段为0
    public static final int value=123;--->在准备阶段为123

解析

 1. 将常量池内的符号引用转换为直接引用
 2. 主要针对类,接口,字段,类方法,接口方法,方法类型,方法句柄,调用点限定符等7类符号引用进行转换

初始化

 1. 执行类构造器<clinit>()初始化类变量和其他资源
 2. <clinit>()自动收集类中所有类变量的赋值操作和静态语句块中的赋值操作,并按照先后顺序初始化   父类的 类变量的赋值操作和静态语句块中的赋值--->子类的 类变量的赋值操作和静态语句块中的赋值

谁主导了类加载

一.显而易见是类加载器(Class Loader)
二.那么都有什么样的类加载器呢,以及分工
 1. 启动类加载器(Bootstrap ClassLoader):
      使用C++语言实现,是虚拟机自身的一部分,
      负责加载<JAVA_HOME>/lib中的符合文件名规范的类
 2. 扩展类加载器(Extension ClassLoader):
      继承自java.lang.ClassLoaderJAVA语言实现
      负责加载<JAVA_HOME>/lib/ext中的符合文件名规范的类
 3. 应用程序类加载器(Application ClassLoader):
      继承自java.lang.ClassLoaderJAVA语言实现,getSystemClassLoader()中可获得,故也可以叫做系统类加载器
      负责加载ClassPath中的符合文件名规范的类
 4. 自定义类加载器(User ClassLoader)
三.加载算法:双亲委派模型
     由下而上委托:Custom(自定义)->App->Extension->Bootstrap
     ps:将加载任务委托给父类加载

     由上而下加载:Bootstrap->Extension->App->Custom(自定义)
     ps:如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载

  这样加载的意义:同一个CLass文件只要被不同类加载器加载,那么这两个类必定不想等。
  通过这个带有优先级的层次关系的加载模型,保证了类的安全和稳定,防止核心API被恶意篡改,防止内存中出现多份同样的字节码。 

破坏双亲委派模型

 1. 重写rt.jar等代码
 2. SPI(Service Provider Interface)扩展:
JNDI属于rt.jar的代码之一,由启动类加载器进行加载,用来对资源进行集中管理和查找,嗲用顺序如下。
JNDI-->线程上下文类加载(Thread Context CLassLoader)-->JDBC,JAXB等服务
 3.OSGi--->代码热替换(HotSwap),模块热部署(Hot Deployment)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值