虚拟机类加载

  • Java虚拟机

    jvm是一个内存中的虚拟机,jvm的存储就是内存,我们所写的类,常量变量方法都在内存中

    picture 6

    • Class Loader:依据特定格式,加载class文件到内存
    • execution engine:对命令进行解析
    • native interface:融合不同的开发语言的原生库为Java所用
    • RuntimeDataArea:Jvm内存空间模型
  • 谈谈反射

    语言描述:

    对于任意一个类,都能够知道这个类的所有属性和方法,对任意一个对象,都能够调用它任意方法和属性,动态调用对象方法的功能称为反射

    实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    public class Robot {
    private String name;
    public void sayHi(String helloSentence){
    System.out.println(helloSentence + " " + name);
    }
    private String throwHello(String tag){
    return "Hello " + tag;
    }
    static {
    System.out.println("Hello Robot");
    }
    }
    public static void main(String[] args) {
    Class rc = Class.forName("com.interview.javabasic.reflect.Robot");
    Robot r = (Robot) rc.newInstance();
    System.out.println("Class name is " + rc.getName());
    //获取私有方法,不可以实现继承和接口的方法
    Method getHello = rc.getDeclaredMethod("throwHello", String.class);
    //设置为true才可以获取私有方法
    getHello.setAccessible(true);
    Object str = getHello.invoke(r, "Bob");
    System.out.println("getHello result is " + str);
    //获取public方法,继承的接口的方法可以获取
    Method sayHi = rc.getMethod("sayHi", String.class);
    sayHi.invoke(r, "Welcome");
    Field name = rc.getDeclaredField("name");
    name.setAccessible(true);
    name.set(r, "Alice");
    sayHi.invoke(r, "Welcome");
    System.out.println(System.getProperty("java.ext.dirs"));
    System.out.println(System.getProperty("java.class.path"));
    }
  • 类从编译到执行的过程

    • 编译器将Robot.java源文件便以为Robot.class字节码文件
    • ClassLoader将字节码转换为jvm中的class对象
    • JVM利用Class对象实例化为Robot对象
  • ClassLoad:

    1. 简介

      主要工作在class类加载阶段,主要作用是从系统外部获得class二进制数据流,所有的class都是由classloader进行加载的,classloader负责通过将class文件里的二进制数据流装载进系统,然后教给虚拟机进行连接,初始化等操作

    2. classLoader的种类:

      • BootStrapClassLoader:C++编写,加载核心库Java.*

      • ExtClassLoader:Java编写,加载扩展库javax.*

      • AppClassLoader:Java编写,加载程序所在目录java.class.path

      • 自定义ClassLoader:Java编写

        继承finalClass:去寻找class文件的

        继承defineClass:去定义一个类:

      picture 7

  • 类加载器的双亲委派模型

    picture 8

    源码分析下:

    picture 9

    picture 10

    为什么需要双亲委派模型?

    1. 避免多份同样的字节码的加载
  • 类的加载方式

    1. 隐式加载:new
    2. 显示加载:loadClass,forName等
    3. LoadClass和forName区别
      • 都是运行时都能知道该类的属性和方法,对于任意一个对象都能调用他的任意方法和属性
      • Class.forName得到的class是已经初始化完成的,ClassLoader.loadClass得到的class是还没有链接的(lazy加载,可以加快速度)
  • 类装载过程

    picture 11

    总体流程:加载->验证->准备->解析->初始化->使用->卸载