java的类加载器ClassLoader

类在执行之前会执行三个步骤:加载 ->   连接  -> 初始化

1.java中类的加载

java 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个Class对象,用来封装类在方法区的数据结构。可以把堆区的Class理解为方法区的一面镜子,对应方法区的类的数据结构,通过这面镜子实现类的调用。

加载.class文件的多种方式:

1.从本地系统中直接加载

2.通过网络下载.class文件

3.从zip,jar里加载.class文件

4.从专有的数据库中提取.class文件

5.将java源文件动态编译为.class文件

 类加载的最终结果是生成位于堆中的Class对象,Class对象封装了类在方法区内的数据结构,并且向java程序员提供了访问方法区内的数据结构的接口

查看源码得到Class对象只能由java虚拟机来创建,其构造函数私有化

2.连接

1. 验证:确保被加载的类的正确性(主要防止恶心的class文件被加载)

2. 准备:为类的静态变量分配内存,并将其初始化为默认值

3. 解析:把类中的符合引用转换为直接引用

3.初始化

    为类的静态变量赋予正确的初始值

所有的java虚拟机实现必须在每一个类或接口被java程序“首次主动使用”时才初始化

java对类的使用方式分为:主动使用,被动使用

主动使用有六种:(除这6种外,其他都是被动使用)

1。创建类的实例

2。访问某个类或接口的静态变量或对该静态变量赋值

3。调用类的静态方法

4。反射

5。初始化类的子类

6。java虚拟机启动时被标注位启动类的类

4.类加载器Classloader

类加载器类型

1.java虚拟机自带的类加载器:

-----根类加载器Bootstrap

该类加载器没有父类加载器,它负责加载虚拟机的核心类库,如java.lang.String等,根类加载器用于在启动JVM时加载类,以使JVM能正常工作,因而它是用Native(c++)代码实现的,最早被创建出来,处于最底层。它并没有继承java.lang.ClassLoader类。

-----扩展类加载器Extension

该类加载器的父类加载器是根类加载器。它从java.ext.dirs系统属性所指定的目录获取加载类库或从JDK的安装目录的jre\lib\ext子目录下加载类库。如果把jar放到这个目录下,也会自动用扩展类加载器加载。扩展类加载器是java类,是java.lang.ClassLoader类的子类

-----系统类加载器System

也成为应用类加载器,它的父类加载器是扩展类加载器,它将加载CLASSPATH中配置的目录和jar文件,它是用户自定义类加载器的默认父类加载器,系统类加载器是java类,是java.lang.ClassLoader类的子类

2.用户自定义类加载器:是java.lang.ClassLoader的子类,可以定义类加载器

类加载器机制

类加载器用来把类加载到java虚拟机中,类加载过程采用的是父亲委托机制,这种机制能很好的保证java平台的安全,因为在这种机制下用户定义的类加载器不可能加载应由父加载器加载的可靠类,如java.lang.String总是由根类加载器加载。在此委托机制中,除了java的根类加载器以外,其余的加载器都有且只有一个父加载器。

自定义类加载器

用户自定义类加载器需要满足父委托机制,默认系统类加载器为其父加载器。要实现自定义加载器,只需要集成ClassLoader类,然后覆盖findClass(String name)方法,该方法根据参数指定加载类的名字,返回对应的Class对象的引用

自定义类加载器类: MyClassLoader

  1. package com.longpo.classloader;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. public class MyClassLoader extends ClassLoader {
  8. private String name; //类加载器的名字
  9. private String path="D:\\"; //加载类的路径
  10. private final String type=".class"; //class文件的扩展名
  11. public MyClassLoader(String name)
  12. {
  13. super();
  14. this.name=name;
  15. }
  16. //指定父类加载器
  17. public MyClassLoader(ClassLoader parent ,String name)
  18. {
  19. super(parent);//显示指定该加载器的父加载器
  20. this.name=name;
  21. }
  22. //设置加载class的路径
  23. public String getPath() {
  24. return path;
  25. }
  26. public void setPath(String path) {
  27. this.path = path;
  28. }
  29. @Override
  30. public String toString() {
  31. return "MyClassLoader :" + name ;
  32. }
  33. //读取对应class文件的二进制数据---这里简单读取
  34. private byte[] loadClassData(String name)
  35. {
  36. //根据要加载的类名找到对应的文件
  37. name=name.replace(".", "\\");//com.longpo.test目录结构是\\
  38. File file=new File(path+name+type);
  39. //根据文件大小来创建字节数组
  40. byte[]bytes=new byte[(int)file.length()] ;
  41. try {
  42. InputStream is = new FileInputStream(file);
  43. int len=is.read(bytes);//返回读取字节的长度
  44. is.close();
  45. } catch (FileNotFoundException e) {
  46. e.printStackTrace();
  47. } catch (IOException e) {
  48. e.printStackTrace();
  49. }
  50. return bytes;
  51. }
  52. //一定要重写该方法
  53. @Override
  54. public  Class<?> findClass(String name) throws ClassNotFoundException {
  55. //得到class文件的二进制数据
  56. byte[]data=loadClassData(name);
  57. return this.defineClass(name, data, 0,data.length);//返回class对象的引用
  58. }
  59. }

定义一个测试加载类:Simple

  1. package com.longpo.classloader;
  2. public class Simple {
  3. public Simple( )
  4. {
  5. System.out.println("Simple的类加载器的名字是:"+this.getClass().getClassLoader());
  6. }
  7. }

测试自定义加载类:Test

  1. package com.longpo.classloader;
  2. public class Test {
  3. public static void main(String[] args) throws Exception{
  4. //loader1的父加载器默认是系统加载器--上面还有系统加载器,扩展加载器,根加载器
  5. MyClassLoader loader1=new MyClassLoader("loader1");
  6. loader1.setPath("D:\\lib\\loader1\\");//loader1加载路径
  7. //loader2的父加载器为loader1--上面有loader1加载器,系统加载器,扩展加载器,根加载器
  8. MyClassLoader loader2=new MyClassLoader(loader1,"loader2");
  9. loader2.setPath("D:\\lib\\loader2\\");//loader2加载路径
  10. //loader3的父加载器为null,即根加载器--上面只有根加载器
  11. MyClassLoader loader3=new MyClassLoader(null,"loader3");
  12. loader3.setPath("D:\\lib\\loader3\\");//loader3加载路径
  13. test(loader2);
  14. test(loader3);
  15. }
  16. public static void test(ClassLoader loader)throws Exception{
  17. Class clazz=loader.loadClass("com.longpo.classloader.Simple");//loadClas会自动调用findClass方法
  18. Object object=clazz.newInstance();
  19. }
  20. }

此时把编译好的class文件发到对应加载器目录的文件夹里面,我用的是Eclipse,可在项目的目录的bin目录下找到.class文件

在Eclipse运行Test,得结果:

各个加载器的关系为

使用loader2加载Simple时,根据父亲委托机制,会从根加载器开始尝试加载,一直往下加载,之道系统类加载器加载成功。使用loader3加载Simple,根据父亲委托机制,先由根加载器加载,加载失败后有loader3自己加载

原文地址 http://techfoxbbs.com/blog-1-2.html

时间: 2024-08-06 16:53:56

java的类加载器ClassLoader的相关文章

java类加载器——ClassLoader

Java的设计初衷是主要面向嵌入式领域,对于自定义的一些类,考虑使用依需求加载原则,即在程序使用到时才加载类,节省内存消耗,这时即可通过类加载器来动态加载. 如果你平时只是做web开发,那应该很少会跟类加载器打交道,但如果你想深入学习tomcat服务器的架构,它是必不可少的.所谓类加载器,就是用于加载Java类到Java虚拟机中,它负责读取Java字节码,并转换成java.lang.Class类的一个实例,使字节代码.class文件得以运行.一般类加载器负责根据一个指定的类找到对应的字节代码,然

浅析java类加载器ClassLoader

作为一枚java猿,了解类加载器是有必要的,无论是针对面试还是自我学习. 本文从JDK提供的ClassLoader.委托模型以及如何编写自定义的ClassLoader三方面对ClassLoader做一个简要的总结. JDK中提供的ClassLoader 1. Bootstrap ClassLoader Bootstrap加载器是用C++语言写的,它是在Java虚拟机启动后初始化的,它主要负责加载%JAVA_HOME%/jre/lib以及%JAVA_HOME%/jre/classes中的类,是最顶

分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码

先回顾一下classpath classpath的作用: classpath的作用是指定查找类的路径:当使用java命令执行一个类(类中的main方法)时,会从classpath中进行查找这个类. 指定classpath的方式一:         设置环境变量CLASSPATH,多个路径之间使用英文的分号隔开,也可以指定为jar包路径.          示例:CLASSPATH=c:/myclasses/;c/mylib/aa.jar;c:/mylib/bb.jar;.          注意

深入理解 java类加载器ClassLoader

类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件).类加载器负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例.每个这样的实例用来表示一个 Java 类.通过此实例的 newInstance()方法就可以创建出该类的一个对象,也就是万能的Class对象. Jav

JAVA之了解类加载器Classloader

1.类的加载.连接和初始化   类初始化通常包括加载.连接.初始化三个步骤. (1)进程的结束 每当运行一个java程序时,将会启动一个java虚拟机进程,不管程序多么复杂,有多少线程,都在这个java虚拟机进程里.以下四种情况会使得该进程被终止-- 程序运行到最后正常结束: 程序里遭遇了System.exit(),或者是Runtime.getRunTime().exit()代码: 程序执行中遇到了未捕获的异常或者错误: java所在平台强制结束了JVM进程: 当该进程结束,那么该进程在内存中的

Java类加载器 ClassLoader的解析

//参考 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器基本概念 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的.Java Applet 需要从远程下载 Java 类文件到浏览器中并执行.现在类加载器在 Web 容器和 O

Java类加载器( CLassLoader ) 死磕 3: 揭秘 ClassLoader抽象基类

[正文]Java类加载器(  CLassLoader ) 死磕3:  揭秘 ClassLoader抽象基类 3.1. 揭秘ClassLoader抽象基类 3.1.1. 类的加载分类:隐式加载和显示加载 java中类是动态加载的,jvm启动的时候,并不会一次性加载所有的class文件,而是根据需要去动态加载.一是加快启动的速度,二是节约内存.如果一次性加载全部jar包的所有class,速度会很慢. 动态载入一个class类,有两种方式: (1) implicit隐式加载 即通过实例化才载入的特性来

【正文】Java类加载器( CLassLoader ) 死磕 4: 神秘的双亲委托机制

[正文]Java类加载器(  CLassLoader ) 死磕4:  神秘的双亲委托机制 本小节目录 4.1. 每个类加载器都有一个parent父加载器 4.2. 类加载器之间的层次关系 4.3. 类的加载次序 4.4 双亲委托机制原理与沙箱机制 4.5. forName方法和loadClass方法的关系 4.6. 使用组合而不用继承 4.7. 各种不同的类加载途径 4.1.每个类加载器都有一个parent父加载器 每个类加载器都有一个parent父加载器,比如加载SystemConfig.cl

jvm之java类加载机制和类加载器(ClassLoader)的详解

当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载.连接.初始化3个步骤来对该类进行初始化.如果没有意外,JVM将会连续完成3个步骤,所以有时也把这个3个步骤统称为类加载或类初始化. 一.类加载过程 1.加载 加载指的是将类的class文件读入到内存,并为之创建一个java.lang.Class对象,也就是说,当程序中使用任何类时,系统都会为之建立一个java.lang.Class对象. 类的加载由类加载器完成,类加载器通常由JVM提供,这些类加载器也是前面所有程序运行的基础