jvm002-类加载子系统

目录

1、内存结构概述

1.1 简图

1.2 详细图 (中文)

1.3 详细图(英文) 

1.4 如果自己手写一个Java虚拟机的话,主要考虑哪些结构呢?

2、类加载器与类加载过程

2.1 类加载子系统的作用

 2.2 类加载ClassLoader扮演的角色

 2.3 类的加载过程

2.3.1 加载阶段

2.3.2 链接阶段

2.3.3 初始化阶段

3、类加载器的分类

3.1 类加载器的分类 

3.1.1 启动类加载器

3.1.2 扩展类加载器 

3.1.3 应用类加载器

3.1.4 自定义类加载器

3.1.5 自定义加载器的实现步骤

4、ClassLoader的使用说明

4.1 关于ClassLoder 

4.2 获取ClassLoader的途径 

5、双亲委派机制

5.1 定义

5.2 工作原理

5.3 举例 

5.4 优势

5.5 沙箱安全机制

6、其他

6.1 判断两个class对象是否为同一个类 

6.2 对类加载器的引用

6.3 类的主动使用和被动使用


1、内存结构概述

1.1 简图

1.2 详细图 (中文)

 

1.3 详细图(英文) 

 

1.4 如果自己手写一个Java虚拟机的话,主要考虑哪些结构呢?

         类加载器 和 执行引擎

2、类加载器与类加载过程

2.1 类加载子系统的作用

 2.2 类加载ClassLoader扮演的角色

 2.3 类的加载过程

 

2.3.1 加载阶段

2.3.2 链接阶段

package com.atguigu.java;

/**
 * @author shkstart
 * @create 2020 下午 6:01
 */
public class ClassInitTest {
   private static int num = 1;

   static{
       num = 2;
       number = 20;
       System.out.println(num);
       //System.out.println(number);//报错:非法的前向引用。
   }

   //linking之prepare: number = 0 --> initial: 20 --> 10
   private static int number = 10;  
   public static void main(String[] args) {
       System.out.println(ClassInitTest.num);//2
       System.out.println(ClassInitTest.number);//10
   }
}

2.3.3 初始化阶段


 

package com.atguigu.java;

/**
 * @author shkstart
 * @create 2020 下午 8:34
 * @desc   <clinit>() 与 类的构造器
 */
public class ClinitTest {
    //任何一个类声明以后,内部至少存在一个类的构造器
    private int a = 1;
    private static int c = 3;
    public static void main(String[] args) {
        int b = 2;
    }

    public ClinitTest(){
        a = 10;
        int d = 20;
    }

}

 


package com.atguigu.java;

public class ClinitFirst {

    public static int a = 18;
    public static int b = 18;

    static {
        b = 20;
    }

    public static void main(String[] args) {
        System.out.println("a="+a+";b="+b);//a=18;b=20
    }
}

类的<clinit>()方法如下

 


package com.atguigu.java;

/**
 * @author shkstart
 * @create 2020 下午 8:40
 * @desc   若该类具有父类,JVM会保证子类的<clinit>()执行前,父类的<clinit>()先执行完毕
 */
public class ClinitTest1 {
    static class Father{
        public static int A = 1;
        static{
            A = 2;
        }
    }

    static class Son extends Father{
        public static int B = A;
    }

    public static void main(String[] args) {
        //加载Father类,其次加载Son类。
        System.out.println(Son.B);//2
    }
}

package com.atguigu.java;

/**
 * @author shkstart
 * @create 2020 上午 11:23
 * @desc   虚拟机必须保证一个类的<clinit>()方法在多线程下被同步加锁
 */
public class DeadThreadTest {
    public static void main(String[] args) {
        Runnable r = () -> {
            System.out.println(Thread.currentThread().getName() + "开始");
            DeadThread dead = new DeadThread();
            System.out.println(Thread.currentThread().getName() + "结束");
        };

        Thread t1 = new Thread(r,"线程1");
        Thread t2 = new Thread(r,"线程2");

        t1.start();
        t2.start();
    }
}

class DeadThread{
    static{
        if(true){
            System.out.println(Thread.currentThread().getName() + "初始化当前类");
            while(true){

            }
        }
    }
}

 

3、类加载器的分类

3.1 类加载器的分类 

 

package com.atguigu.java1;

/**
 * @author shkstart
 * @create 2020 上午 9:22
 */
public class ClassLoaderTest {
    public static void main(String[] args) {

        //获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2

        //获取其上层:扩展类加载器
        ClassLoader extClassLoader = systemClassLoader.getParent();
        System.out.println(extClassLoader);//sun.misc.Launcher$ExtClassLoader@1540e19d

        //获取其上层:获取不到引导类加载器
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println(bootstrapClassLoader);//null

        //对于用户自定义类来说:默认使用系统类加载器进行加载
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2

        //String类使用引导类加载器进行加载的。---> Java的核心类库都是使用引导类加载器进行加载的。
        ClassLoader classLoader1 = String.class.getClassLoader();
        System.out.println(classLoader1);//null


    }
}
package com.atguigu.java1;

import sun.security.ec.CurveDB;

import java.net.URL;
import java.security.Provider;

/**
 * @author shkstart
 * @create 2020 上午 12:02
 */
public class ClassLoaderTest1 {
    public static void main(String[] args) {
        System.out.println("**********启动类加载器**************");
        //获取BootstrapClassLoader能够加载的api的路径
        URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs();
        for (URL element : urLs) {
            System.out.println(element.toExternalForm());
        }
        //从上面的路径中随意选择一个类,来看看他的类加载器是什么:引导类加载器
        ClassLoader classLoader = Provider.class.getClassLoader();
        System.out.println(classLoader);

        System.out.println("***********扩展类加载器*************");
        String extDirs = System.getProperty("java.ext.dirs");
        for (String path : extDirs.split(";")) {
            System.out.println(path);
        }

        //从上面的路径中随意选择一个类,来看看他的类加载器是什么:扩展类加载器
        ClassLoader classLoader1 = CurveDB.class.getClassLoader();
        System.out.println(classLoader1);//sun.misc.Launcher$ExtClassLoader@1540e19d

    }
}

 

3.1.1 启动类加载器

3.1.2 扩展类加载器 

3.1.3 应用类加载器

3.1.4 自定义类加载器

3.1.5 自定义加载器的实现步骤

package com.atguigu.java1;

import java.io.FileNotFoundException;

/**
 * 自定义用户类加载器
 * @author shkstart
 * @create 2019 下午 12:21
 */
public class CustomClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        try {
            byte[] result = getClassFromCustomPath(name);
            if(result == null){
                throw new FileNotFoundException();
            }else{
                return defineClass(name,result,0,result.length);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        throw new ClassNotFoundException(name);
    }

    private byte[] getClassFromCustomPath(String name){
        //从自定义路径中加载指定类:细节略
        //如果指定路径的字节码文件进行了加密,则需要在此方法中进行解密操作。
        return null;
    }

    public static void main(String[] args) {
        CustomClassLoader customClassLoader = new CustomClassLoader();
        try {
            Class<?> clazz = Class.forName("One",true,customClassLoader);
            Object obj = clazz.newInstance();
            System.out.println(obj.getClass().getClassLoader());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

4、ClassLoader的使用说明

4.1 关于ClassLoder 

4.2 获取ClassLoader的途径 

package com.atguigu.java1;

/**
 * @author shkstart
 * @create 2020 上午 10:59
 */
public class ClassLoaderTest2 {
    public static void main(String[] args) {
        try {
            //1.
            ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();
            System.out.println(classLoader);
            //2.
            ClassLoader classLoader1 = Thread.currentThread().getContextClassLoader();
            System.out.println(classLoader1);

            //3.
            ClassLoader classLoader2 = ClassLoader.getSystemClassLoader().getParent();
            System.out.println(classLoader2);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

 

5、双亲委派机制

5.1 定义

5.2 工作原理

5.3 举例 

5.4 优势

5.5 沙箱安全机制

6、其他

6.1 判断两个class对象是否为同一个类 

6.2 对类加载器的引用

6.3 类的主动使用和被动使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值