首先介绍下ClassLoader:

ClassLoader顾名思义就是类加载器,负责将Class加载到JVM中,事实上ClassLoader除了能将Class加载到JVM中之外,还有一个重要的作用就是审查每个类应该有谁加载,ClassLoader是一个父优先的等级加载机制。ClassLoader除了上述两个作用外还有一个任务就是将Class字节码重新解析成JVM统一要求的对象格式-----------由此本文可以划分成三点

  1. ClassLoader类结构分析

    1. ClassLoader常用的方法



    1,defineClass():用来将byte字节流解析成JVM能够识别的Class对象

    2,findClass():用来子类扩展的方法,目的是为了寻找类

    3,loadClass():加载类,这里就可以动态加载了,程序运行的时候加载

    4,resolveClass():这个方法是用来链接这个类

    JDK给我们提供了可以扩展的,也就是我们可以自定义的类加载器URLCLassLoader,比较方便

     2. ClassLoader的等级加载机制

1,BootStrap ClassLoader:

这是一个引导类加载器,首先声明一下虽说在类的结构中可以看到这个类,但是这个类只有Class文件,据了解这个类是通过C++编写的,这也就是ExtClassLoader的父类为空的原因。引导类负责加载JDK的jre下的类库,例如rt.jar

2,ExtClassLoader:

这是一个扩展类加载器,加载bin目录下的ext文件夹下的jar包,不多说

 3,AppClassLoader:

这个类加载器就是我们自定义的类,例如我们的这个方法getSystemClassLoader()作为父加载器,这个加载器也就是AppClassLoader。

 4,加载类过程总结:

看了很多资料都是什么双亲委托加载机制,具体我也不是很清楚,可以我太low,但是我个人的理解就是,当加载一个类的时候:首先检查这个类是否已经被自己加载过,如果已经加载过,就拒绝本次加载,如果没有加载过,就会抛给他的父类,然后父类在检查是否加载,然后在抛给父类,直到全部检查完都没有发现这个类被加载,那么就有意思了,因为每一个类加载器都有自己的加载范围,然后开始判断,父类不加载类,那么就开始向下寻找这个类的加载器,然后这个类被加载,也就是先向上检查是否加载,其次向下看是否可以加载!--------------------这里有一个讲解,来帮助理解,如果我们自己写了一个java.lang.String,那么类加载器就先去加载jdk下的java.lang.String.遇到我们自己定义的类就不会加载了,这也就是java.lang.Object首先被加载,父类加载会防止我们破坏干扰jre的正常运行,导致类结构被破坏

这里是类关系的代码

public class ClassA {
}
public class ClassB {
}
public class ClassTest {
public static void main(String[] args) {
//演示 我們的類加載器
System.out.println("ClassTest-------------ClassLoader:"+ClassTest.class.getClassLoader());
System.out.println("ClassTest.Parent------ClassLoader:"+ClassTest.class.getClassLoader().getParent());
System.out.println("ClassTest.GrandFather-ClassLoader:"+ClassTest.class.getClassLoader().getParent().getParent()); //用户自定义的类加载 都是通过AppClassLoader加载
System.out.println(ClassA.class.getClassLoader());
System.out.println(ClassB.class.getClassLoader());
//结论就是----------当两个类名称不同,那么这两个类就不相同
}
}

打印结果

ClassTest-------------ClassLoader:sun.misc.Launcher$AppClassLoader@73d16e93
ClassTest.Parent------ClassLoader:sun.misc.Launcher$ExtClassLoader@15db9742
ClassTest.GrandFather-ClassLoader:null
sun.misc.Launcher$AppClassLoader@73d16e93
sun.misc.Launcher$AppClassLoader@73d16e93
  1. 如何判断两个类相同
  • 类名称不同
这里就不需要介绍了,只要类名不同,那么类肯定也不同
  • 包名称不同
package me.classloader.classpackage;

public class String {

}

package me.classloader.classpackage;

import org.junit.Test;

public class ClassTest {
@Test
public void classTest(){
//这里是 BootStrap ClassLoader-------因此返回Null
System.out.println(java.lang.String.class+"------classLoader:"+java.lang.String.class.getClassLoader());
//这里 我们自定义的类 被AppClassLoader 加载
System.out.println(String.class+"--------ClassLoader:"+String.class.getClassLoader());
//很明显这两个类是不同的
}
}
这里可以得到我们的包名可以引起 两个类不是同一个类,并且,这里JVM就近调用一个类先调用的同包下的类
  • 类加载器不同
package me.classloader.classloader;

public class Demo {
private Demo demo; public void setDemo(Demo demo) {
this.demo = demo;
} } package me.classloader.classloader; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; //自己写的ClassLoader
public class MyClassLoader extends ClassLoader { private String classPath;// 类路径 public MyClassLoader() {
} public MyClassLoader(String classPath) { this.classPath = classPath;
} @Override
protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] classDate = getDate(name);
if (classDate == null) {
throw new ClassNotFoundException();
} else {
return defineClass(name, classDate, 0, classDate.length);
}
} // 将 class 文件转化成字节流
//className是类名称---权限定名
private byte[] getDate(String className) {
// 将XX.XX.java --------->XX/XX/java.class
String path = classPath + File.separatorChar + className.replace('.', File.separatorChar) + ".class";
try {
InputStream is = new FileInputStream(path);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int num = 0;
while ((num = is.read(buffer)) != -1) {
stream.write(buffer, 0, num);
}
return stream.toByteArray(); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
} package me.classloader.classloader; public class ClassTest {
public static void main(String[] args) throws Exception{
String classPath ="E:\\javaprogram\\java-exercise\\classload\\bin";
String className = "me.classloader.classloader.Demo";
ClassLoader appClassLoader = ClassTest.class.getClassLoader();
MyClassLoader myClassLoader = new MyClassLoader(classPath);
Class demo1 = appClassLoader.loadClass(className);
System.out.println(demo1.newInstance().getClass().getClassLoader());
Class demo2 = myClassLoader.findClass(className);
System.out.println(demo2.newInstance().getClass().getClassLoader());
System.out.println(demo1.newInstance().getClass() ==demo2.newInstance().getClass());
}
}
测试结果
sun.misc.Launcher$AppClassLoader@73d16e93
me.classloader.classloader.MyClassLoader@6d06d69c
false

通过上面的代码,我们也知道了如何写一个类加载器,其实查看findClass()是ClassLoader提供的一个模板方法!

总结:类加载器也是一个比较深的东西,例如servlet中jsp使用了热部署!其实就是类加载器的应用,可能动态代理也用到了类加载器,因为实际工作加载的是我们代理的类

深入分析ClassLoader的更多相关文章

  1. JVM学习十一:JVM之深入分析ClassLoader

    本章节准备写的是对类加载器ClassLoader的剖析,但因为前面已经对类加载器做过一些简单的分析和双亲委派机制的分析:因此本章节的侧重点在于实例演示和自定义加载器. 一.什么是ClassLoader ...

  2. 第六章 深入分析ClassLoader工作机制

    补充(非书中): Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件).类加载器负责读取Java字节代码,并转换成 java.lan ...

  3. JVM学习四:深入分析ClassLoader

    一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...

  4. 深入分析Java Web技术内幕(修订版)

    阿里巴巴集团技术丛书 深入分析Java Web技术内幕(修订版)(阿里巴巴集团技术丛书.技术大牛范禹.玉伯.毕玄联合力荐!大型互联网公司开发应用实践!) 许令波 著   ISBN 978-7-121- ...

  5. 《深入分析Java Web技术内幕》读书笔记 - 第1章 深入Web请求过程

    第1章 深入Web请求过程 1 1.1 B/S网络架构概述 2 基于统一的应用层协议HTTP来交互数据. 1.2 如何发起一个请求 4 HTTP连接本质是建立Socket连接.请求实现方式:工具包如H ...

  6. JAVA Coder 的《深入分析Java Web 技术内幕》读书笔记

    本文基于<深入分析Java Web 技术内幕> <深入分析Java Web 技术内幕>,作者是 许令波,电子工业出版社.本文只是记录书本当中的精彩部分,作个人回顾和技术分享,请 ...

  7. Java - 收藏集 -

    Java - 收藏集 -   Java 基础思维导图,让 Java 不再难懂 - 工具资源 - 掘金思维导图的好处 最近看了一些文章的思维导图,发现思维导图真是个强大的工具.了解了思维导图的作用之后, ...

  8. <JVM中篇:字节码与类的加载篇>04-再谈类的加载器

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

  9. 深入分析Java ClassLoader原理

    一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...

随机推荐

  1. JavaScript的3大组成部分&&ECMAScript函数&&闭包

    1.JavaScript实现是由ECMAScript.DOM和BOM组成.a.ECMAScript仅仅是一个描述,定义了脚本语言的所有属性.方法和对象.b.DOM[文档对象模型]是HTML和XML的应 ...

  2. PHP 去除HTML标签 HTML实体转字符 br转\n

    1.去除HTML标签 strip_tags(string,allow)//剥去字符串中的 HTML 标签,但允许使用 <img> 标签:$str =  strip_tags($str,&q ...

  3. Linux一些零碎

    1.设置时间和市区 1.tzselect 2.sudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

  4. SVG知识难点

      参考资料:http://www.w3cplus.com/css3/clip.html   1.clip:默认值是auto,为不裁剪 <img border="0" src ...

  5. nginx1.8安装nginx_concat_module及400错误解决办法

    nginx安装concat模块可以合并js,css等静态资源,减少http请求 在nginx源码目录执行命令: ./configure --user=www --group=www --prefix= ...

  6. ElasticSearch基本学习

    ES介绍 维基百科使用Elasticsearch来进行全文搜做并高亮显示关键词,以及提供search-as-you-type.did-you-mean等搜索建议功能. 英国卫报使用Elasticsea ...

  7. Model Validation in ASP.NET Web API By Mike Wasson|July 20, 2012 268 of 294 people found this helpful

    using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using ...

  8. [转] vim自定义配置 和 在ubnetu中安装vim

    Ubuntu 12.04安装vim和配置   问题: ubuntu默认没有安装vim,出现: jyg@ubuntu:~$ vim test.cThe program 'vim' can be foun ...

  9. Android 自定义 view(四)—— onMeasure 方法理解

    前言: 前面我们已经学过<Android 自定义 view(三)-- onDraw 方法理解>,那么接下我们还需要继续去理解自定义view里面的onMeasure 方法 推荐文章: htt ...

  10. 第一部分:连接MYSQL数据库代码

    <?php $connec=mysql_connect("localhost","root","root") or die(" ...