类在执行之前会执行三个步骤:加载 -> 连接 -> 初始化
1.类的加载
类的加载指的是将类的.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
package com.longpo.classloader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; public class MyClassLoader extends ClassLoader { private String name; //类加载器的名字 private String path="D:\\"; //加载类的路径 private final String type=".class"; //class文件的扩展名 public MyClassLoader(String name) { super(); this.name=name; } //指定父类加载器 public MyClassLoader(ClassLoader parent ,String name) { super(parent);//显示指定该加载器的父加载器 this.name=name; } //设置加载class的路径 public String getPath() { return path; } public void setPath(String path) { this.path = path; } @Override public String toString() { return "MyClassLoader :" + name ; } //读取对应class文件的二进制数据---这里简单读取 private byte[] loadClassData(String name) { //根据要加载的类名找到对应的文件 name=name.replace(".", "\\");//com.longpo.test目录结构是\\ File file=new File(path+name+type); //根据文件大小来创建字节数组 byte[]bytes=new byte[(int)file.length()] ; try { InputStream is = new FileInputStream(file); int len=is.read(bytes);//返回读取字节的长度 is.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bytes; } //一定要重写该方法 @Override public Class<?> findClass(String name) throws ClassNotFoundException { //得到class文件的二进制数据 byte[]data=loadClassData(name); return this.defineClass(name, data, 0,data.length);//返回class对象的引用 } }
定义一个测试加载类:Simple
package com.longpo.classloader; public class Simple { public Simple( ) { System.out.println("Simple的类加载器的名字是:"+this.getClass().getClassLoader()); } }
测试自定义加载类:Test
package com.longpo.classloader; public class Test { public static void main(String[] args) throws Exception{ //loader1的父加载器默认是系统加载器--上面还有系统加载器,扩展加载器,根加载器 MyClassLoader loader1=new MyClassLoader("loader1"); loader1.setPath("D:\\lib\\loader1\\");//loader1加载路径 //loader2的父加载器为loader1--上面有loader1加载器,系统加载器,扩展加载器,根加载器 MyClassLoader loader2=new MyClassLoader(loader1,"loader2"); loader2.setPath("D:\\lib\\loader2\\");//loader2加载路径 //loader3的父加载器为null,即根加载器--上面只有根加载器 MyClassLoader loader3=new MyClassLoader(null,"loader3"); loader3.setPath("D:\\lib\\loader3\\");//loader3加载路径 test(loader2); test(loader3); } public static void test(ClassLoader loader)throws Exception{ Class clazz=loader.loadClass("com.longpo.classloader.Simple");//loadClas会自动调用findClass方法 Object object=clazz.newInstance(); } }
此时把编译好的class文件发到对应加载器目录的文件夹里面,我用的是Eclipse,可在项目的目录的bin目录下找到.class文件
在Eclipse运行Test,得结果:
各个加载器的关系为
使用loader2加载Simple时,根据父亲委托机制,会从根加载器开始尝试加载,一直往下加载,之道系统类加载器加载成功。使用loader3加载Simple,根据父亲委托机制,先由根加载器加载,加载失败后有loader3自己加载
相关推荐
《深入Java虚拟机(七)深入源码看java类加载器ClassLoader》 Java类加载器(ClassLoader)在Java运行环境中扮演着至关重要的角色。它负责将类的字节码加载到Java虚拟机(JVM)中,使得程序能够运行。ClassLoader是...
Java 类加载器 ClassLoader 用法解析 Java 中的类加载器(ClassLoader)是一种机制,负责将类从文件系统、JAR 文件或网络等来源加载到 Java 虚拟机中。类加载器的作用是将类的二进制数据加载到内存中,并为其创建一...
### Java 类加载器详解 #### 一、类加载器概述 在Java中,类加载器(Class Loader)是一项核心机制,用于将字节码(.class文件)加载到JVM中,使其成为运行时的对象。类加载器不仅实现了类的加载功能,还确保了...
Java类加载器分为三种主要类型:引导类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用程序类加载器(Application ClassLoader,也称为系统类加载器)。它们共同工作,确保了Java...
**java应用程序类加载器(ClassLoader for java Application)**: 当我们创建一个Java应用程序时,比如通过`java MainClass`命令启动,实际上是由应用程序类加载器来执行的。它查找并加载包含主类(Main-Class ...
2. **Extension ClassLoader** (扩展类加载器): 负责加载扩展类库,通常位于`JAVA_HOME/lib/ext`目录下的jar包。 3. **Application ClassLoader** (应用程序类加载器): 也称为系统类加载器,负责加载用户定义的类...
上述代码展示了如何创建一个自定义类加载器`MyClassLoader`,该类继承自`java.lang.ClassLoader`。`MyClassLoader`的主要功能是从文件系统中加载指定类的二进制数据。 - **构造函数**:接受一个父类加载器和基础...
### Java ClassLoader (类加载器)详解 #### 一、教程提示 如果你正在查看这份文档,在线版中你可以点击下面的任何主题直接跳转到相应的部分。 1. **教程提示** 2. **介绍** 3. **类加载器结构** 4. **编译类加载...
Java 类加载器原理 Java 类加载器是Java虚拟机(JVM)的核心组成部分,它负责将类的字节码加载到内存中并转换为可执行的Java类。类加载器的作用不仅仅是加载类,还包括确保类的唯一性,避免重复加载,并且遵循特定...
Java的ClassLoader类加载器机制 在 Java 虚拟机(JVM)中,类加载器(ClassLoader)扮演着非常重要的角色。类加载器负责加载 Java 类,包括核心类和用户自定义类。在 JVM 运行过程中,类加载器会形成一个层次结构,...
2. Extension ClassLoader:扩展类加载器,负责加载`<JAVA_HOME>/lib/ext`目录下的扩展类库,或者被`-Djava.ext.dirs`指定的路径中的类。 3. Application ClassLoader:也称为系统类加载器,负责加载用户类路径`-cp...
2. **Extension ClassLoader(扩展类加载器)**:它加载位于`JAVA_HOME/lib/ext`目录下的JAR包和用户指定的扩展目录下的类库。 3. **System ClassLoader(系统类加载器)**:也称为应用程序类加载器,它负责加载用户...
Java中的类加载器主要有三种:Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader。它们按照双亲委派模型工作,从根加载器开始,逐级尝试加载类。当我们想要对类进行加密时,可以创建一个自定义的类...
2. **Extension ClassLoader**:扩展类加载器,负责加载`<JAVA_HOME>\lib\ext`目录下的JAR包,或者被`-Djava.ext.dirs`指定的路径中的类。 3. **System ClassLoader**:也称为应用类加载器,负责加载`CLASSPATH`...
类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java ...
**类加载器(ClassLoader)**是Java虚拟机(JVM)中的一个重要组成部分,它负责将编译好的`.class`文件加载到JVM中,使得这些类可以在Java环境中运行。类加载器不仅能够加载类,还能够根据不同的需求定制加载方式,如从...
在Java中,类加载器主要分为三个层次:Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader。Bootstrap ClassLoader负责加载JDK的核心库,如rt.jar;Extension ClassLoader则加载JRE扩展目录下的jar文件...
Java的类加载器主要有Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader。Bootstrap ClassLoader是JVM启动时的第一个类加载器,负责加载JDK的`<JAVA_HOME>/jre/lib`目录下的核心类库。Extension ...
【深入探讨 Java 类加载器】 Java 类加载器是Java虚拟机(JVM)的核心组成部分,它的主要任务是将Java类的字节码加载到JVM中以便执行。类加载器的概念始于JDK 1.0,最初是为了解决Java Applet在浏览器中的运行需求...