博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java核心: 类加载器ClassLoader原理
阅读量:7144 次
发布时间:2019-06-29

本文共 4445 字,大约阅读时间需要 14 分钟。

hot3.png

一、什么是ClassLoader

先看一下JDK对ClassLoader的定义:

A class loader is an object that is responsible for loading classes. The class ClassLoaderis an abstract class. Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a "class file" of that name from a file system.     Every Class object contains a reference to the ClassLoader that defined it.     Class objects for array classes are not created by class loaders, but are created automatically as required by the Java runtime. The class loader for an array class, as returned by Class.getClassLoader() is the same as the class loader for its element type; if the element ype is a primitive type, then the array class has no class loader.     Applications implement subclasses of ClassLoader in order to extend the manner in which the Java virtual machine dynamically loads classes.     Class loaders may typically be used by security managers to indicate security domains.     The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself.     The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.     Class loaders that support concurrent loading of classes are known as parallel capable class loaders and are required to register themselves at their class initialization time by invoking the ClassLoader.registerAsParallelCapable method. Note that the ClassLoader class is registered as parallel capable by default. However, its subclasses still need to register themselves if they are parallel capable.     In environments in which the delegation model is not strictly hierarchical, class loaders need to be parallel capable, otherwise class loading can lead to deadlocks because the loader lock is held for the duration of the class loading process (see loadClass methods).     Normally, the Java virtual machine loads classes from the local file system in a platform-dependent manner. For example, on UNIX systems, the virtual machine loads classes from the directory defined by the CLASSPATH environment variable.     However, some classes may not originate from a file; they may originate from other sources, such as the network, or they could be constructed by an application. The method defineClass converts an array of bytes into an instance of class Class. Instances of this newly defined class can be created using Class.newInstance.     The methods and constructors of objects created by a class loader may reference other classes.To determine the class(es) referred to, the Java virtual machine invokes the loadClass method of the class loader that originally created the class.

二、ClassLoader加载类的原理

 1、原理介绍

       ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。

2、为什么要使用双亲委托这种模型呢?

       因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义的类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时就被引导类加载器(Bootstrcp ClassLoader)加载,所以用户自定义的ClassLoader永远也无法加载一个自己写的String,除非你改变JDK中ClassLoader搜索类的默认。

3、 但是JVM在搜索类的时候,又是如何判定两个class是相同的呢?

     JVM在判定两个class是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。只有两者同时满足的情况下,JVM才认为这两个class是相同的。就算两个class是同一份class字节码,如果被两个不同的ClassLoader实例所加载,JVM也会认为它们是两个不同class。比如网络上的一个Java类org.classloader.simple.NetClassLoaderSimple,javac编译之后生成字节码文件NetClassLoaderSimple.class,ClassLoaderA和ClassLoaderB这两个类加载器并读取了NetClassLoaderSimple.class文件,并分别定义出了java.lang.Class实例来表示这个类,对于JVM来说,它们是两个不同的实例对象,但它们确实是同一份字节码文件,如果试图将这个Class实例生成具体的对象进行转换时,就会抛运行时异常java.lang.ClassCaseException,提示这是两个不同的类型。

三、ClassLoader实战-Tomcat类加载机制

转载于:https://my.oschina.net/u/206123/blog/822628

你可能感兴趣的文章
mysql日志问题定位实用命令
查看>>
【LeetCode】257. Binary Tree Paths
查看>>
MySQL SQL优化之in与range查询【转】
查看>>
jQuery 有条件排序
查看>>
有趣html5(两)----使用canvas结合剧本画在画布上的简单图(html5另一个强大)...
查看>>
可方便扩展的JIRA Rest Web API的封装调用
查看>>
strcmp的源码实现
查看>>
Java多线程7:死锁
查看>>
概率图形模型(PGM)学习笔记(四)-贝叶斯网络-伯努利贝叶斯-贝叶斯多项式...
查看>>
worker_pool的例子
查看>>
(转)gethostbyname() -- 用域名或主机名获取IP地址
查看>>
Android 插件化
查看>>
Yii2的深入学习--自动加载机制
查看>>
sqlserver修改增删改字段
查看>>
设计模式介绍、分类、原则
查看>>
超级好用的解析JSON数据的网站
查看>>
C#正则表达式匹配任意字符
查看>>
Objective-c中@interface、@implementation、@protocal
查看>>
Python yield 使用浅析
查看>>
支持移动设备的图片展示插件
查看>>