Java ClassLoader 类加载器
来源:互联网 发布:百度搜索软件 编辑:程序博客网 时间:2024/04/26 15:22
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
加载 就是指将class文件读入内存,并为之创建一个Class对象。 任何类被使用时系统都会建立一个Class对象。
连接
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值(静态成员,类的创建而创建)
解析 将类的二进制数据中的符号引用替换为直接引用
初始化 就是我们以前讲过的初始化步骤
加载器
1. Bootstrap ClassLoader
负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
2. Extension ClassLoader
负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
3. App ClassLoader
负责记载classpath中指定的jar包及目录中class
4. Custom ClassLoader
属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader
加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。
类的初始化
类什么时候才被初始化:
1)创建类的实例,也就是new一个对象
2)访问某个类或接口的静态变量,或者对该静态变量赋值
3)调用类的静态方法
4)反射(Class.forName("com.lyj.load"))
5)初始化一个类的子类(会首先初始化子类的父类)
6)JVM启动时标明的启动类,即文件名和类名相同的那个类
只有这6中情况才会导致类的类的初始化。
自定义加载器
public class CustomClassLoader extends ClassLoader { // 要加载的类 private String name; // 设置父加载器和需要加载的类 public CustomClassLoader(ClassLoader parent , String name) { super(parent); if(name == null || name.length() <= 0) throw new NullPointerException(); this.name = name; } // 重写加载器 @Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { Class<?> clazz = null; /**如果是我们想要热加载的类则调用我们重写的findClass方法来加载**/ if(this.name.equals(name) && !"java".equals(name)){ // 调用系统加载class文件 clazz = findLoadedClass(name); if(clazz == null) // 调用自定义的 clazz = findClass(name); // 类的生命周期包括:加载、验证、准备、解析、初始化、使用、卸载。其中验证、准备、解析统称为连接 //如果类已连接过,resolveClass方法会直接返回 if(resolve) resolveClass(clazz); return clazz; } // 调用父加载器 return super.loadClass(name , resolve); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { // 获得实际存储class文件位置 String fileName = c2f(name); // 读取class文件 byte[] bytes = f2b(fileName); // 根据class文件生成Class类对象 return defineClass(name, bytes, 0, bytes.length); } // 类名转为文件名 private String c2f(String name){ /**编译后的class文件存放的目录**/ String baseDir = "F:\\classes"; name = name.replace("." , File.separator); name = baseDir + name + ".class"; return name; } // 读取文件byte数组 private byte[] f2b(String fileName){ RandomAccessFile file = null; FileChannel channel = null; byte[] bytes = null; try { /**随机存取文件对象,只读取模式**/ file = new RandomAccessFile(fileName , "r"); /**NIO文件通道**/ channel = file.getChannel(); /**NIO字节缓冲**/ ByteBuffer buffer = ByteBuffer.allocate(1024); int size = (int) channel.size(); bytes = new byte[size]; int index = 0; /**从NIO文件通道读取数据**/ while (channel.read(buffer) > 0){ /**字节缓冲从写模式转为读取模式**/ buffer.flip(); while (buffer.hasRemaining()){ bytes[index] = buffer.get(); ++index; } /**字节缓冲的readerIndex、writerIndex置零**/ buffer.clear(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if (channel != null) { try { channel.close(); } catch (IOException e) { e.printStackTrace(); } } if (file != null) { try { file.close(); } catch (IOException e) { e.printStackTrace(); } } } return bytes; } // 加载 public Class<?> loadClass(){ try { // 调用系统loadClass(name,false) return loadClass(name); } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } } }
public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException {String name = "top.xfdtm.test.Person";CustomClassLoader loader = new CustomClassLoader(Thread.currentThread().getContextClassLoader(), name);Class<?> clazz = loader.loadClass();Object obj = clazz.newInstance();}
0 0
- java类加载器classLoader
- Java ClassLoader 类加载器
- java类加载器ClassLoader .
- java类加载器classloader
- Java ClassLoader 类加载器
- Java类加载器 ClassLoader
- java ClassLoader类加载器
- Java类加载/ClassLoader
- Java 类加载Classloader
- Java类加载ClassLoader
- JAVA ClassLoader加载类
- java中的ClassLoader类加载器
- Java类加载器(ClassLoader)浅析
- 类的加载器 java.lang.ClassLoader
- Java 类加载器( ClassLoader)浅析
- Java基础加强---ClassLoader(类加载器)
- Java虚拟机学习 - 类加载器(ClassLoader)
- Java虚拟机学习 - 类加载器(ClassLoader)
- 网易18实习生网测题--吃豆子
- ScrollView嵌套TextView文字上部截断下部有空隙
- 使用moy快速开发后台管理系统(四)
- BSI TR-03110
- JavaScript不懂的东西
- Java ClassLoader 类加载器
- #升级Android Studio2.3遇到的奇葩问题及最终解决方法
- 自考学习总结
- TensorFlow开源的三个原因
- 加载巨图
- 利用FFmpeg将pcm文件转成wav文件
- [笔记]算法复习笔记---栈、队列、链表(中)
- 报文交换和分组交换
- 链表问题(4)-- 环形单链表的约瑟夫问题