tomcat 7 中的类加载器学习

tomcat 7自带很多junit测试用例,可以帮助我们窥探源码的秘密。以下使用来测试类加载器的一个测试用例。类加载器也是对象,他们用来将类从类从。class文件加载到虚拟机,这些已经讲了很多,深入jvm中说的很详细,什么双亲委派模型,在书中还以tomcat为例讲解。


/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.loader;


import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


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


import org.junit.Assert;
import org.junit.Test;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
import org.apache.tomcat.util.buf.ByteChunk;


public class TestWebappClassLoader extends TomcatBaseTest {


@Test
public void testGetURLs() throws Exception {


File f = new File("test/webresources/war-url-connection.war");


String[] expected = new String[2];
String warUrl = f.toURI().toURL().toExternalForm();
expected[0] = "jar:" + warUrl + "!/WEB-INF/classes/";
expected[1] = "jar:" + warUrl + "!/WEB-INF/lib/test.jar";


Tomcat tomcat = getTomcatInstance();
// Must have a real docBase - just use temp
StandardContext ctx =
(StandardContext)tomcat.addContext("", f.getAbsolutePath());


tomcat.start();


//获得当前的类加载器
ClassLoader cl = ctx.getLoader().getClassLoader();


Assert.assertTrue(cl instanceof URLClassLoader);
//获得类加载器中对应的路径


try (URLClassLoader ucl = (URLClassLoader) cl) {
URL[] urls = ucl.getURLs();
Assert.assertEquals(expected.length, urls.length);
String[] actual = new String[urls.length];
for (int i = 0; i < urls.length; i++) {
actual[i] = urls[i].toExternalForm();
System.out.println(actual[i]);
}
Assert.assertArrayEquals(expected, actual);
//获得类加载器的各级父类加载器
while(cl!=null)
{
System.out.println(cl);
cl=cl.getParent();

}

}
}
@Test
public void testBug53454() throws Exception {
Tomcat tomcat = getTomcatInstance();


// Must have a real docBase - just use temp
StandardContext ctx = (StandardContext)
tomcat.addContext("", System.getProperty("java.io.tmpdir"));
System.out.println("临时目录"+System.getProperty("java.io.tmdir"));


// Map the test Servlet
MyServlet largeBodyServlet = new MyServlet();
Tomcat.addServlet(ctx, "MyServlet", largeBodyServlet);
ctx.addServletMapping("/", "MyServlet");


tomcat.start();


Map<String,List<String>> resHeaders= new HashMap<>();
int rc = headUrl("http://localhost:" + getPort() + "/", new ByteChunk(),
resHeaders);


Assert.assertEquals(HttpServletResponse.SC_OK, rc);
ClassLoader cl=ctx.getClass().getClassLoader();
while(cl!=null)
{
System.out.println(cl);
cl=cl.getParent();
}

}
private static class MyServlet extends HttpServlet {


private static final long serialVersionUID = 1L;


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

}

}
}


 

输出结果:

临时目录null

[email protected]
[email protected]

jar:file:/F:/javal/Tomcat-Research-trunk/test/webresources/war-url-connection.war!/WEB-INF/classes/
jar:file:/F:/javal/Tomcat-Research-trunk/test/webresources/war-url-connection.war!/WEB-INF/lib/test.jar
WebappClassLoader
  context:
  delegate: false
----------> Parent Classloader:
[email protected]

[email protected]
[email protected]
一月 26, 2015 6:52:56 下午 org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["http-nio-127.0.0.1-auto-2-64075"]
一月 26, 2015 6:52:56 下午 org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["http-nio-127.0.0.1-auto-2-64075"]

如果使用临时目录和默认目录,应用的类加载器是AppClassLoader,而其的目录可以每个应用的类加载器为WebappClassLoader

时间: 2024-10-01 04:17:42

tomcat 7 中的类加载器学习的相关文章

Java中的类加载器

转载:http://blog.csdn.net/zhangjg_blog/article/details/16102131 从java的动态性到类加载机制 我们知道,Java是一种动态语言.那么怎样理解这个"动态"呢?或者说一门语言具备了什么特性,才能称之为动态语言呢?对于java,我是这样理解的. 我们都知道JVM(java虚拟机)执行的不是本地机器码指令,而是执行一种称之为字节码的指令(存在于class文件中).这就要求虚拟机在真正执行字节码之前,先把相关的class文件加载到内存

java类加载器学习2——自定义类加载器和父类委托机制带来的问题

一.自定义类加载器的一般步骤 Java的类加载器自从JDK1.2开始便引入了一条机制叫做父类委托机制.一个类需要被加载的时候,JVM先会调用他的父类加载器进行加载,父类调用父类的父类,一直到顶级类加载器.如果父类加载器加载不了,依次再使用其子类进行加载.当然这类所说的父类加载器,不一定他们之间是继承的关系,有可能仅仅是包装的关系. Java之所以出现这条机制,因为是处于安全性考虑.害怕用户自己定义class文件然后自己写一个类加载器来加载原本应该是JVM自己加载的类.这样会是JVM虚拟机混乱或者

随笔18 java中的类加载器

类的加载是由类加载器完成的,类加载器包括:根加载器( BootStrap ).扩展加载器( Extension ).系统加载器( System )和用户自定义类加载器( java.lang.ClassLoader 的子类).从 Java 2 ( JDK 1.2 )开始,类加载过程采取了父亲委托机制(PDM ). PDM 更好的保证了 Java 平台的安全性,在该机制中, JVM 自带的 Bootstrap 是根加载器,其他的加载器都有且仅有一个父类加载器.类的加载首先请求父类加载器加载,父类加载

java中的类加载器ClassLoader和类初始化

每个类编译后产生一个Class对象,存储在.class文件中,JVM使用类加载器(Class Loader)来加载类的字节码文件(.class),类加载器实质上是一条类加载器链,一般的,我们只会用到一个原生的类加载器AppClassLoader,它只加载Java API等可信类,通常只是在本地磁盘中加载,这些类一般就够我们使用了.如果我们需要从远程网络或数据库中下载.class字节码文件,那就需要我们来挂载额外的类加载器. 一般来说,类加载器是按照树形的层次结构组织的,每个加载器都有一个父类加载

[读书笔记]java中的类加载器

以下内容大多来自周志明的<深入理解Java虚拟机>. 类加载器是java的一项创新,也是java流行的重要原因之一,它最初是为了满足java applet的需求而开发出来. 什么是applet? 作为新手,都不知道applet是什么鬼,看看百度百科的解释,应该就明白了: JavaApplet就是用Java语言编写的小应用程序,可以直接嵌入到网页中,并能够产生特殊的效果. 所以Applet就目前来看 我们用不到了,但是类加载器却在类层次划分.OSGI.热部署.代码加密等领域大放异彩,成为了JAV

深入理解JVM虚拟机7:JNDI,OSGI,Tomcat类加载器实现

打破双亲委派模型 JNDI JNDI 的理解 JNDI是 Java 命名与文件夹接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之中的一个,不少专家觉得,没有透彻理解JNDI的意义和作用,就没有真正掌握J2EE特别是EJB的知识. 那么,JNDI究竟起什么作用?//带着问题看文章是最有效的 要了解JNDI的作用,我们能够从“假设不用JNDI我们如何做?用了JNDI后我们又将如何做?”这个问题来探讨. 没有JNDI的做法: 程序猿开发时,

Java虚拟机JVM学习05 类加载器的父委托机制

Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap) 扩展类加载器(Extension) 系统类加载器(System) 2.用户自定义的类加载器: java.lang.ClassLoader的子类,用户可以定制类的加载方式. JVM自带的加载器 Java虚拟机自带了以下几种加载器. 1.根(Bootstrap)类加载器: 该加载器没有父加载器. 它

【学习札记-类加载器】

个人学习整理,如有不足之处,请不吝指教.转载请注明:@CSU-Max 类加载器 简介 类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件).类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例.每个这样的实例用来表示一个 Java 类.通过此实例的 new

Android中插件开发前篇之----类加载器

前言 关于插件,已经在各大平台上出现过很多,eclipse插件.chrome插件.3dmax插件,所有这些插件大概都为了在一个主程序中实现比较通用的功能,把业务相关或者让可以让用户自定义扩展的功能不附加在主程序中,主程序可在运行时安装和卸载.在android如何实现插件也已经被广泛传播,实现的原理都是实现一套插件接口,把插件实现编成apk或者dex,然后在运行时使用DexClassLoader动态加载进来,不过在这个开发过程中会遇到很多的问题,所以这一片就先不介绍如何开发插件,而是先解决一下开发