Java类加载器(二)

类加载原理及双亲委托模型

我看见双亲委托模型的时候,第一反应是把关注点放在了“双”上,以为它有两个父类。其实,这里的双亲,就是指父类。

当一个ClassLoader实例需要加载某个类时,它不会首先自己去寻找(搜索)这个类,而是把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的BootStrap ClassLoader试图加载,如果没有加载到(不在它管控的范围),则把任务交给Extension ClassLoader,如果也没加载到,则继续转交给App ClassLoader进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或者网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException;否则将这个找到的类生成一个类的定义,并将它加载到内存中,最后返回这个类在内存中的Class实例对象。

同一份class字节码文件,但是由于被两个不同的ClassLoader实例所加载,所以JVM认为它们就是两个不同的类。

ClassLoader Theory

上图引用自xyang0917的深入分析Java ClassLoader原理

验证ClassLoader加载类的原理

打印ClassLoader类的层次结构

public class ClassLoaderTest {
    public static void main(String[] args) {
        ClassLoader loader = ClassLoaderTest.class.getClassLoader();
        while (loader != null) {
            System.out.println(loader);
            loader = loader.getParent();
        }
        System.out.println(loader);
    }
}

输出结果如下:

sun.misc.Launcher$AppClassLoader@232204a1
sun.misc.Launcher$ExtClassLoader@74a14482
null

输出结果解释:

  • 第一行结果说明:ClassLoaderTest的类加载器是AppClassLoader。
  • 第二行结果说明:AppClassLoader的类加器是ExtClassLoader,即parent=ExtClassLoader。
  • 第三行结果说明:ExtClassLoader的类加器是Bootstrap ClassLoader,因为Bootstrap ClassLoader不是一个普通的Java类,所以ExtClassLoader的parent=null,所以第三行的打印结果为null就是这个原因。

Tomcat自定义了几个类加载器

实验版本是apache-tomcat-8.5.23

新建一个自定义Servlet

package cn.cecurio;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ClassLoaderServletTest extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=UTF-8");
		Writer out = resp.getWriter();
		ClassLoader classLoader = this.getClass().getClassLoader();
		StringBuffer sBuffer = new StringBuffer();
		while (classLoader != null) {
			sBuffer.append(classLoader.getClass().getName() + "<br />");
			classLoader = classLoader.getParent();
		}
		out.write(sBuffer.toString());
		out.write(String.valueOf(classLoader));
		out.flush();
		out.close();
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doGet(req, resp);
	}
}

在web.xml中配置Servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
	http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	
	<display-name>tomcat-test</display-name>
	
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	
	<servlet>
		<servlet-name>classLoaderServletTest</servlet-name>
		<servlet-class>cn.cecurio.ClassLoaderServletTest</servlet-class>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>classLoaderServletTest</servlet-name>
		<url-pattern>/servlet/classLoaderServletTest</url-pattern>
	</servlet-mapping>
</web-app>

结果

web app classloader test

参考文档

http://blog.csdn.net/xyang81/article/details/7292380

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值