jvm---类加载器(1)

1.jvm虚拟机内存模型

   类加载子系统
    运行时数据区:  堆
                  栈
                  本地方法栈
                  方法区(元空间):常量+静态变量+类元信息
                  程序计数器
    字节码执行引擎

2.类加载过程

 加载; 在硬盘上查找并通过IO读入字节码文件,使用类时才会加载,例如调用类的main()方法,new对象等等
 验证: 校验字节码文件的正确性
 准备: 给类的静态变量分配内存,并赋予默认值
 解析: 将符号引用替换为直接引用,该阶段会把一些静态方法(符号引用,比如main()方法)替换为指向数据所存内存的指针,
      或句柄等(直接引用),这是所谓的静态连接过程(类加载期间完成),动态链接是在程序运行期间完成的将符号引用替换为
      直接引用
 初始化: 对类的静态变量初始化为指定的值,执行静态代码块
public class Tuling {
    
    
   public static void main(String[] args) {
    
    
       System.out.println(String.class.getClassLoader());
       System.out.println(com.sun.crypto.provider.DESedeKeyFactory.class.getClassLoader().getClass().getName());
       System.out.println(Tuling.class.getClassLoader().getClass().getName());
       System.out.println(ClassLoader.getSystemClassLoader().getClass().getName());
   }

运行结果:
null
sun.misc.Launcher$ExtClassLoader

sun.misc.Launcher$AppClassLoader

sun.misc.Launcher$AppClassLoader

3.类加载器:

启动类加载器: jvm运行的位于jre/lib 目录下的核心类库 比如:rt.jar, charsets.jar等
扩展类加载器: 负责加载 位于jie的lib目录下的ext扩展目录中的jar类包
应用程序类加载器: 负责加载classPath路径下的类包,主要就是加载你自己写的那些类
自定义加载器:负责加载用户自定义路径下的类包

4. 查看jvm字节码执行情况

  • javap -c Tuling.class

5. 自定义类加载器 和类加载器不生效的处理

  • https://www.cnblogs.com/sunhao1234/p/12343967.html
    // 自定义类加载器
package com.tuling;

/**
 * Title: User
 * Description: TODO
 *
 * @author hfl
 * @version V1.0
 * @date 2020-11-23
 */
public class User {
    
    
    private String name;
    private int age;

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    @Override
    protected void finalize() throws Throwable {
    
    
        System.out.println("关闭资源,user " + name + "即将回收");
    }

    public void sout(){
    
    
        System.out.println("=============自己的加载器加载类调用方法============");
    }

}

package com.tuling;

import java.io.FileInputStream;
import java.lang.reflect.Method;

/**
 * Title: MyClassLoaderTest
 * Description: TODO
 *
 * @author hfl
 * @version V1.0
 * @date 2020-11-23
 */
public class MyClassLoaderTest {
    
    
    static class MyClassLoader extends ClassLoader {
    
    
        private String classPath;

        public MyClassLoader(String classPath) {
    
    
            this.classPath = classPath;
        }

        private byte[] loadByte(String name) throws Exception {
    
    
            name = name.replaceAll("\\.", "/");
            FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
            int len = fis.available();
            byte[] data = new byte[len];
            fis.read(data);
            fis.close();
            return data;
        }

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
    
    

            try {
    
    
                byte[] data = loadByte(name);
                return defineClass(name, data, 0, data.length);
            } catch (Exception e) {
    
    
                e.printStackTrace();
                throw new ClassNotFoundException();
            }
        }
    }

    public static void main(String[] args) throws Exception {
    
    
        MyClassLoader classLoader = new MyClassLoader("D:/test");
        Class<?> clazz = classLoader.loadClass("com.tuling.User");
        Object obj = clazz.newInstance();
        Method method = clazz.getDeclaredMethod("sout", null);
        method.invoke(obj, null);
        System.out.println(clazz.getClassLoader().getClass().getName());
    }
}

运行结果:

=自己的加载器加载类调用方法
com.tuling.MyClassLoaderTest$MyClassLoader


猜你喜欢

转载自blog.csdn.net/baidu_21349635/article/details/110009735