zoukankan      html  css  js  c++  java
  • JVM类加载

    仅以此记录学习笔记等!

    JVM整体的加载过程

    声明周期:

    JVM伴随Java程序的开始而开始,程序的结束而停止。一个Java程序会开启一个JVM进程,一台计算机上可以运行多个程序,也就可以运行多个JVM进程。

    JVM将线程分为两种:守护线程和普通线程。守护线程是JVM自己使用的线程,比如垃圾回收(GC)就是一个守护线程。普通线程一般是Java程序的线程,只要JVM中有普通线程在执行,那么JVM就不会停止。

     

    启动大概过程:

    img

    launcher是一个static且new初始化的变量(即单例)

    lancher构造方法会初始化ext类加载器、再由得到的ext类加载器去加载app类加载器。

    (app类加载器父类是ext类加载器,ext类加载器原则上是引导类加载器,但引导类是c++创建的,所以其父类加载器为null)

    classLoader->即app类加载器,launcher源码体现。

    ClassLoader:

    img

    loadClass的类加载过程

    加载(load)>>链接(link)(验证**>>准备>>解析)>>初始化(initialize)>>使用>**>卸载

    • 加载:在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,例如调用类的Main()方法,new对象等等,在加载阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

    • 验证:校验字节码文件的正确性(语义合法、符合逻辑)、文件格式验证(需要符合class文件格式)、元数据验证、符号引用验证(确保解析能够正确执行)等。

    • 准备:给类的静态变量分配内存,并赋予默认值(如:int的给0,boolean的给false),final变量直接赋值。这个时候不包括实例变量,实例变量会在对象实例化的时候随着对象一块分配在Java堆中。

    • 解析:将符号引用替换为直接引用(内存地址),该阶段会把一些静态方法(符号引用,比如main()方法)替换为指向数据所存内存的指针或句柄等(直接引用),这就是所谓的静态链接过程。动态链接是在程序运行期间完成的将符号引用替换为直接引用(每个类名、方法、包路径等都是一个符号 存在于常量池中,运行时加载到运行时常量池中javap xx.class -v 查看)。

    • 初始化:对类的静态变量初始化为指定的值,执行静态代码块。

    img

    类被加载到方法区中后主要包含 运行时常量池、类型信息、字段信息、方法信息、类加载器的引用、对应class实例的引用等信息。

     

    类加载器

    • 引导类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如rt.jar、charsets.jar等

    • 扩展类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录中的JAR类包

    • 应用程序类加载器:负责加载CLassPath路径下(项目路径)的类包,主要就是加载自己写的类

    • 自定义加载器:负责加载用户自定义路径下的类包

     

    双亲委派机制

    img

    说明:JVM定义从应用程序类加载器开始加载(具体可看launcher源码 方法getClassLoader()),加载某个类时会委托父加载器寻找目标类,找不到再委托上层父加载器加载,如果所有父加载器都无法在自己的加载类路径下找到目标类,则向下查找并载入目标类。

    比如User类,先找到app类加载器加载,app类加载器先委托ext加载器加载,ext加载器再委托引导类加载器加载,引导类加载器在其类加载路径中找不到User类,则向下退回加载User类的请求,ext收到回复就自己加载,ext在其类加载路径中找不到User类,又向下退回给app类加载器,app类加载器则在自己的类加载路径里找User类,找到了则自己加载。95%以上都是app类加载器应用。(源码->appClassLoader的loadClass,跳到super的ClassLoader 的loadClas方法,重点->UrlClassLoader的findCass(name),装载类即 defineClass() 去类路径拿到class文件)

     

    为什么要设计双亲委派机制?

    • 沙箱安全机制:自己的java.lang.String.class类不会被加载,防止核心API库被篡改。

    根据双亲委派机制,先会向上加载一次,String类是引导类加载器加载的,这时候引导类加载器找到的是JDK自己的String类且返回(只会加载自己定义的类),再向下回到app类中,这时候调用则会报错。

    • 避免类的重复加载:向上委托,如果父加载器已经加载过了某个类,则会直接返回,子ClassLoader就不会再次加载一次,保证被加载类的唯一性。

     

    全盘委托机制

    全盘负责 指的是,当一个ClassLoader加载一个类时,除非显示的使用另外一个ClassLoader,该类所依赖及引用的类也由这个ClassLoader载入。(如User类里用到了 Menu类,这时Menu的加载也是由User 的App类加载器加载)

     

    自定义类加载器

    初始化自定义类加载器,会先初始化父类加载器(默认是app类加载器),其中把自定义类加载器的父类设定为app类加载器,符合双亲委派机制。

    1继承ClassLoader

    2重写findClass方法

    核心就是UrlClassLoader的loadClass()方法(实现双亲委派机制)和findClass()方法(装载类)。

     

    打破双亲委派机制

    不委托父加载器先加载了,在自定义加载器获得了直接返回。

    重写loadClass方法 去掉双亲委派的逻辑

     

    Tomcat如何实现打破双亲委派机制

    基于自定义的类加载器,是自定义类型的时,不委托父加载器加载。

    我始终记住:青春是美丽的东西,而且对我来说,它永远是鼓舞的源泉。——(现代)巴金
  • 相关阅读:
    转载: 如何让form表单在enter键入时不提交
    26个Jquery使用小技巧
    PHP网站页面静态化的生成方法介绍
    用jquery绑定输入框正在输入时返回操作
    PHP开发规范手册之PHP代码规范详解
    Web开发中9个有用的提示和技巧
    TSINGSEE青犀视频边缘计算网关EasyNVR在视频整体监控解决方案中的应用分析
    应急消防通道总是被占用?安防告警视频平台越加必要
    新冠疫情涨涨落落,企业做好线上办公该如何转型?
    【解决方案】如何实现AI自动识别高空抛物行为?
  • 原文地址:https://www.cnblogs.com/flyinglion/p/14799958.html
Copyright © 2011-2022 走看看