}

1.类加载过程

image-20200927203353315

1.类加载器的作用:

image-20200927204938145

image-20200927210810471

2.类加载过程

a.加载-loading

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

image-20200927211312833

b.链接-linking

  • 验证(verify):
    • 确保class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性。
    • 文件格式验证,元数据验证,字节码验证,符号引用验证
  • 准备(prepare):
    • 为类变量分配内存并且设置该类变量的默认初始值,即0
    • 不包含被final修饰的static,应为final在编译的时候就会分配了,准备阶段会显示初始化
    • 不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。
  • 解析(resolve):
    • 将常量池内的符号内容引用转换为直接引用的流程
    • 解析操作往往会伴随则JVM在执行完初始化之后在执行
    • 符号引用就是一组符号来描述所引用的目标。
    • 直接引用就是直接指向目标的指针,相对偏移量或一个间接定位到目标的句柄
    • 解析动作主要针对类或接口,字段,类方法,接口方法,方法类型等
    • CONSTANT_Class_info,CONSTANT_Fieldref_info,CONSTANT_Mehodref_info等

c.初始化-initialization

  • 初始化阶段就是执行类构造器方法< clinit > ()的过程
  • 这个方法不用定义,是javac编译器自动收集类中的所有变量的赋值动作和静态代码块中的语句 合并而来
  • 构造器方法中的指令按语句在源文件中出现的顺序执行。
  • < clinit >()不同于类的构造器
  • 若该类有父类,jvm会保证子类的< clinit >()执行前,父类的已经执行完毕
  • 虚拟机必须保证一个类的< clinit >()方法在多线程下被同步加锁

image-20200928131617852

3.类加载器的分类

image-20200928132450800

image-20200928132608939

a.启动类加载器(bootstrap ClassLoader)

image-20200928134054303

b.扩展类加载器(Extension ClassLoader)

image-20200928134341689

c.应用程序类加载器(系统类加载器,AppClassLoader)

image-20200928140955507

d.用户自定义类加载器

image-20200928141059440

image-20200928142957938

4.ClassLoader

image-20200928144355636

image-20200928144727555

ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();
System.out.println("classLoader = " + classLoader);

ClassLoader classLoader1 = Thread.currentThread().getContextClassLoader();
System.out.println("classLoader1 = " + classLoader1);

ClassLoader classLoader2 = ClassLoader.getSystemClassLoader();
System.out.println("classLoader2 = " + classLoader2);

5.双亲委派机制

Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将他的class文件加载到内存中生成class对象。而且加载某个类的class文件时,java虚拟机采用的是双亲委派模式,就是把请求交由父类处理,它是一种任务委派模式

image-20200928150509891

案例

自己定义一个java.lang.String

package java.lang;

public class String {
    static {
        System.out.println("这是我的string类");
    }
}
package JavaVirtualMachine.loader;

public class ParentDelegationDemo {
    public static void main(String[] args) {
        String s = new String();
        System.out.println(s);
    }
}

测试结果:

并没有打印出定义在静态代码块中的输出语句,这是因为双亲委派机制的存在。

关于包名是java开头的都由 bootstrap classLoader加载,而我们自定义的 java.lang.String不属于这个范畴

image-20200928151826918

作用:

  • 避免类的重复加载
  • 保护程序安全,防止核心API被修改
    • 比如说自定义一个 java.lang.String

java.lang.SecurityException: Prohibited package name: java.lang

image-20200928152633875

沙箱安全机制

image-20200928152801480

6.类的主动使用和被动使用

image-20200928153234093

posted @ 2020-10-06 11:54  likelovecode  阅读(106)  评论(0)    收藏  举报