知识大全 一个简单的自定义ClassLoader的实现

Posted 资源

篇首语:学向勤中得,萤窗万卷书。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 一个简单的自定义ClassLoader的实现相关的知识,希望对你有一定的参考价值。

一个简单的自定义ClassLoader的实现  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  很多时候人们会使用一些自定义的ClassLoader 而不是使用系统的Class Loader 大多数时候人们这样做的原因是 他们在编译时无法预知运行时会需要那些Class 特别是在那些appserver中 比如tomcat Avalon phonix Jboss中 或是程序提供一些plug in的功能 用户可以在程序编译好之后再添加自己的功能 比如ant jxta shell等 定制一个ClassLoader很简单 一般只需要理解很少的几个方法就可以完成   一个最简单的自定义的ClassLoader从ClassLoader类继承而来 这里我们要做一个可以在运行时指定路径 加载这个路径下的class的ClassLoader   通常我们使用ClassLoader loadClass(String):Class方法 通过给出一个类名 就会得到一个相应的Class实例 因此只要小小的改动这个方法 就可以实现我们的愿望了   源码     protected synchronized Class loadClass(String name boolean resolve) throws ClassNotFoundException // First check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) try if (parent != null) c = parent loadClass(name false); else c = findBootstrapClass (name); catch(ClassNotFoundException e) // If still not found then call findClass in order // to find the class c = findClass(name); if (resolve) resolveClass(c); return c;    Source from ClassLoader java    First check JavaAPI doc 上面指出了缺省的loadClass方法所做的几个步骤    调用findLoadedClass(String):Class 检查一下这个class是否已经被加载过了 由于JVM 规范规定ClassLoader可以cache它所加载的Class 因此如果一个class已经被加载过的话 直接从cache中获取即可    调用它的parent 的loadClass()方法 如果parent为空 这使用JVM内部的class loader(即著名的bootstrap classloader)    如果上面两步都没有找到 调用findClass(String)方法来查找并加载这个class   后面还有一句话 在Java 版本以后 鼓励用户通过继承findClass(String)方法实现自己的class loader而不是继承loadClass(String)方法   既然如此 那么我们就先这么做 )    public class AnotherClassLoader extends ClassLoader private String baseDir;private static final Logger LOG = Logger getLogger(AnotherClassLoader class); public AnotherClassLoader (ClassLoader parent String baseDir) super(parent); this baseDir = baseDir; protected Class findClass(String name) throws ClassNotFoundException LOG debug( findClass + name); byte[] bytes = loadClassBytes(name); Class theClass = defineClass(name bytes bytes length);//A if (theClass == null) throw new ClassFormatError(); return theClass; private byte[] loadClassBytes(String className) throws ClassNotFoundException try String classFile = getClassFile(className); FileInputStream fis = new FileInputStream(classFile); FileChannel fileC = fis getChannel(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); WritableByteChannel outC = Channels newChannel(baos); ByteBuffer buffer = ByteBuffer allocateDirect( ); while (true) int i = fileC read(buffer); if (i == || i == ) break; buffer flip(); outC write(buffer); buffer clear(); fis close(); return baos toByteArray(); catch (IOException fnfe) throw new ClassNotFoundException(className); private String getClassFile(String name) StringBuffer sb = new StringBuffer(baseDir); name = name replace( File separatorChar) + class ; sb append(File separator + name); return sb toString();     [i]Ps:这里使用了一些JDK 的nio的代码 )[/i]  很简单的代码 关键的地方就在A处 我们使用了defineClass方法 目的在于把从class文件中得到的二进制数组转换为相应的Class实例 defineClass是一个native的方法 它替我们识别class文件格式 分析读取相应的数据结构 并生成一个class实例     还没完呢 我们只是找到了发布在某个目录下的class 还有资源呢 我们有时会用Class getResource():URL来获取相应的资源文件 如果仅仅使用上面的ClassLoader是找不到这个资源的 相应的返回值为null     同样我们看一下原来的ClassLoader内部的结构     public URL getResource(String name) name = resolveName(name); ClassLoader cl = getClassLoader ();//这里 if (cl==null) // A system class return ClassLoader getSystemResource(name); return cl getResource(name);      原来是使用加载这个class的那个classLoader获取得资源       public URL getResource(String name) URL url; if (parent != null) url = parent getResource(name); else url = getBootstrapResource(name); if (url == null) url = findResource(name);//这里 return url;          这样看来只要继承findResource(String)方法就可以了 修改以下我们的代码       //新增的一个findResource方法protected URL findResource(String name) LOG debug( findResource + name); try URL url = super findResource(name); if (url != null) return url; url = new URL( file:/// + converName(name)); //简化处理 所有资源从文件系统中获取 return url; catch (MalformedURLException mue) LOG error( findResource mue); return null; private String converName(String name) StringBuffer sb = new StringBuffer(baseDir); name = name replace( File separatorChar); sb append(File separator + name); return sb toString();      好了 到这里一个简单的自定义的ClassLoader就做好了 你可以添加其他的调料(比如安全检查 修改class文件等) 以满足你自己的口味 )     cha138/Article/program/Java/JSP/201311/19625

相关参考

知识大全 开发Eclipse下的自定义控件[4]

开发Eclipse下的自定义控件[4]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  作为一个可

知识大全 利用窗体的自定义属性实现窗体传值

  第步在解决方案上添加一个窗体Form;并添加textBoxtextBoxButton将Button的标题设为确定DialogResult属性设为OK  第步在窗体Form的类代

知识大全 JSP的自定义标签

JSP的自定义标签  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  一基本概念  标签(Tag):

知识大全 JQuery的自定义事件代码,触发,绑定

JQuery的自定义事件代码,触发,绑定  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  自定义事

知识大全 使用有趣的自定义标记来布局页面

  今天我们来学习如何使用有趣的自定义标记来布局页面有的朋友可能有这样的疑问自己随便定义的标记浏览器怎么能正确的认识呢?  这里我们就要用到文档的命名空间那么命名空间又是指什么?  大家知道XML有一

知识大全 开发Eclipse下的自定义控件[2]

开发Eclipse下的自定义控件[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!addPain

知识大全 开发Eclipse下的自定义控件[3]

开发Eclipse下的自定义控件[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!addMous

知识大全 开发Eclipse下的自定义控件[5]

开发Eclipse下的自定义控件[5]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!publicv

知识大全 开发Eclipse下的自定义控件[6]

开发Eclipse下的自定义控件[6]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!publicv

知识大全 开发Eclipse下的自定义控件[1]

开发Eclipse下的自定义控件[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  本文首先介