务实java虚拟机——双亲委派模型详解

类加载器

务实java虚拟机——双亲委派模型详解_第1张图片

类加载器和类共同决定了一个类在java虚拟机中的唯一性。Java保持着三层类加载器,双亲委派的类加载架构,类加载器层次结构从上到下是启动类加载器、平台类加载器、应用程序类加载器、自定义加载器。

双亲委派模型我竟然被“双亲委派”给虐了 - 知乎

务实java虚拟机——双亲委派模型详解_第2张图片

这中层次关系称为双亲委派模型,双亲委派加载机制是当一个类加载器加载一个类时,首先将加载这个类的任务交给其父类类加载器,然后一直向上直到启动类加载器,如果父类类加载器不能加载才交给子类加载器去加载,这样保证了基础类性在不同的环境中是同一个类。

jvm对class文件采用的是按需加载的方式,当需要使用该类时,jvm才会将它的class文件加载到内存中产生class对象。

好处(为什么需要双亲委派?):

1、使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.Object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。

2、通过委派的方式,可以避免类的重复加载,当父加载器已经加载过某一个类时,子加载器就不会再重新加载这个类。

如何实现双亲委派机制:

1、先检查类是否已经被加载过

2、若没有加载则调用父加载器的loadClass()方法进行加载

3、若父加载器为空则默认使用启动类加载器作为父加载器。

4、如果父类加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。

如何主动破坏双亲委派机制?

因为他的双亲委派过程都是在loadClass方法中实现的,那么想要破坏这种机制,那么就自定义一个类加载器,重写其中的loadClass方法,使其不进行双亲委派即可。

为什么Tomcat要破坏双亲委派

我们知道,Tomcat是web容器,那么一个web容器可能需要部署多个应用程序。

不同的应用程序可能会依赖同一个第三方类库的不同版本,但是不同版本的类库中某一个类的全路径名可能是一样的。

如多个应用都要依赖hollis.jar,但是A应用需要依赖1.0.0版本,但是B应用需要依赖1.0.1版本。这两个版本中都有一个类是com.hollis.Test.class。

如果采用默认的双亲委派类加载机制,那么是无法加载多个相同的类。

所以,Tomcat破坏双亲委派原则,提供隔离的机制,为每个web容器单独提供一个WebAppClassLoader加载器。

Tomcat的类加载机制:为了实现隔离性,优先加载 Web 应用自己定义的类,所以没有遵照双亲委派的约定,每一个应用自己的类加载器——WebAppClassLoader负责加载本身的目录下的class文件,加载不到时再交给CommonClassLoader加载,这和双亲委派刚好相反。

 

 

你可能感兴趣的:(务实java虚拟机,java,jvm,开发语言)