- 浏览: 127626 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
wind35:
32赞~~~
KDB+ database -
sunnyxiaoxi:
图片看不到
KDB+ database 初步 -
RonQi:
确实很有用的插件
eclipse插件 快速打开文件位置,在命令行打开文件位置 -
zhanshi258:
我们程序员讲究的是严谨,大部分人是讲娱乐
小唠叨 -
li498833284:
因为很多都是屏蔽字
小唠叨
转载自 http://www.javaresearch.org/article/1007.htm
很多时候人们会使用一些自定义的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 = findBootstrapClass0(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方法所做的几个步骤。 1. 调用findLoadedClass(String):Class 检查一下这个class是否已经被加载过了,由于JVM 规范规定ClassLoader可以cache它所加载的Class,因此如果一个class已经被加载过的话,直接从cache中获取即可。 2. 调用它的parent 的loadClass()方法,如果parent为空,这使用JVM内部的class loader(即著名的bootstrap classloader)。 3. 如果上面两步都没有找到,调用findClass(String)方法来查找并加载这个class。后面还有一句话,在Java 1.2版本以后,鼓励用户通过继承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, 0, 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(1024);
while (true) { int i = fileC.read(buffer);
if (i == 0 || i == -1) {
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:这里使用了一些JDK1.4的nio的代码:)[/i] 很简单的代码,关键的地方就在A处,我们使用了defineClass方法,目的在于把从class文件中得到的二进制数组转换为相应的Class实例。defineClass是一个native的方法,它替我们识别class文件格式,分析读取相应的数据结构,并生成一个class实例。 还没完呢,我们只是找到了发布在某个目录下的class,还有资源呢。我们有时会用Class.getResource():URL来获取相应的资源文件。如果仅仅使用上面的ClassLoader是找不到这个资源的,相应的返回值为null。 同样我们看一下原来的ClassLoader内部的结构。
public java.net.URL getResource(String name) {
name = resolveName(name); ClassLoader cl = getClassLoader0();//这里
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文件等),以满足你自己的口味:)
发表评论
-
入手Git
2013-09-18 21:57 1038原本项目一直托管在sourceforge上面. http: ... -
以插件的方式把myeclipse安装到eclipse
2013-04-27 16:56 85871, 请注意eclipse版本问题,笔者用的是eclips ... -
从与大牛richard stallman 聊来的感受
2012-04-25 10:03 940老头非常敬业热心, 写邮件给他, 就算没有时间马上回, 也会有 ... -
Jar Class Finder
2012-04-15 22:38 945Jar Class Finder Jar与Class的查找工 ... -
sourceforge 历程
2012-04-14 19:36 0入门 http://newbiedoc.sourceforg ... -
版本控制之MKS integrity 2007
2011-01-06 16:28 0在新项目中用到了版本控制MKS integrity 2007 -
Open-source License
2010-03-04 11:22 1948Open-source License(转载) ... -
Java 多线程与并发编程专题
2009-11-18 15:55 685http://www.ibm.com/developerwor ... -
浅析Context Class Loader
2009-11-19 11:33 1133转载自 薛笛的专栏http://blog.csdn.net/k ... -
JVM调优总结
2009-11-19 15:35 789转载自http://gq913.iteye.com ... -
Ant build.xml 模板
2009-11-23 14:04 1015<?xml version="1.0" ... -
用javac编译生成不同版本的源码和目标class
2009-11-24 14:47 906转载请自 Ken Wu`s Blog! 合理使用javac的 ... -
java内存模型详解
2009-11-24 14:50 772转载自 Ken Wu`s Blog! 内存模型 (memo ... -
bootstrap类加载原理
2009-11-24 14:53 903转载自 Ken Wu`s Blog! 让我们一起跟随Clas ... -
很详细的Log4j配置
2009-11-25 11:01 711来自: http://www.blogjava.net/zJu ... -
Log4j日志文件的使用
2009-11-25 17:32 908转自 http://blog.csdn.net/edg_edu ... -
另一个好的ant文件收藏
2009-11-26 13:30 924<?xml version="1.0" ... -
提示补全组件:Kissy Suggest
2009-11-26 14:06 1016转自 http://www.iteye.com/topic/4 ... -
String in Java
2009-11-26 15:36 782转自 http://hxraid.iteye.com/blog ... -
dom4j读写xml文件
2010-01-29 09:34 945首先我们给出一段示例程序: importjava.io.F ...
相关推荐
下面我们将详细讨论ClassLoader的基本概念、工作流程以及如何自定义ClassLoader。 1. **ClassLoader的基本概念** - 类加载器是Java中的一个核心组件,它负责将类的.class文件加载到JVM中,并转换为可执行的Java...
以下是一个简单的自定义ClassLoader示例,它能从指定的jar文件加载类: ```java public class MyClassLoader extends URLClassLoader { public MyClassLoader(String jarPath) throws MalformedURLException { ...
在这个简单的例子中,我们将探讨类加载器的基本概念、工作原理以及如何自定义类加载器。 类加载器的主要任务是查找并加载类的.class文件。Java中的类加载过程分为三个阶段:加载、验证、准备、解析和初始化。在我们...
本文将深入探讨Java中的类加载机制,并通过一个具体的自定义类加载器的例子来帮助理解其工作原理。 #### 二、Java类加载器的基本概念 Java中的类加载器主要负责完成以下三个基本任务: 1. **加载(Loading)**:...
Java 2引入的findClass方法使得创建自定义ClassLoader变得更加容易,我们只需要覆盖findClass,而无需完全实现loadClass,简化了过程。 自定义ClassLoader的工作原理是,首先创建一个ClassLoader的实例,然后使用这...
以下是一个简单的例子: ```java public class DynamicClassLoader extends ClassLoader { public Class<?> findClass(byte[] b) throws ClassNotFoundException { return defineClass(null, b, 0, b.length); }...
"classloader-playground"项目的核心是一个简单的Java依赖隔离容器类。在实际开发中,我们常常需要隔离不同模块之间的依赖,避免版本冲突或循环依赖等问题。类加载器可以在这方面发挥重要作用,通过定制类加载器,...
`web_classloader_test`可能包含了这样的自定义类加载器的实现。 5. **热部署与热更新**:在开发阶段,开发者可能希望在不重启服务器的情况下更新代码。这就需要类加载器支持类的动态加载和卸载。这个测试可能包含...
本文将深入探讨自定义类加载器的基本概念、工作原理以及如何创建一个简单的基于磁盘的自定义类加载器。 ### 类加载器的层次结构 Java中的类加载器通常形成一个树状的层次结构,其中Bootstrap ClassLoader是最顶层...
下面是一个简单的自定义类加载器示例: ```java public class MyClassLoader extends ClassLoader { public MyClassLoader(ClassLoader parent) { super(parent); } @Override protected Class<?> findClass...
动态加载类通常涉及自定义ClassLoader,这是因为它允许我们覆盖默认的加载行为,例如从网络、数据库或其他非标准位置加载类。 对于Java源文件动态编译,我们可以使用Java的内置工具`javac`或`javax.tools.Java...
以下是一个简单的自定义类加载器示例,用于动态加载D盘下的A.class文件: ```java package jvm; import java.io.File; import java.io.FileInputStream; import java.lang.reflect.Method; import java.net.URL; ...
通过自定义ClassLoader,开发者可以实现更为复杂的应用架构,如插件系统、动态代码更新等,极大地提升了Java应用程序的可扩展性和维护性。在进行系统设计时,充分考虑类装载的原理和实现,可以帮助我们构建更加健壮...
本文主要探讨了Java代码执行漏洞中类动态加载的应用,特别是通过自定义ClassLoader和反射调用`defineClass`方法来实现字节码的动态解析。 首先,Java中类的加载方式有两种:显式加载和隐式加载。隐式加载通常发生在...
下面通过一个小例子测试这三个JVM自带的ClassLoader之间的关系: ```java public class ClassLoaderTest1 { public static void main(String[] args) { ClassLoader loader = ClassLoaderTest1.class....
在使用自定义 Classloader 加载 JAR 包时,我们需要实现一个自定义的 Classloader 类,并在其中加载要加载的 JAR 包。这种方法比较复杂,需要专门的讨论。 以上四种方法都可以用来执行 JAR 包,但是它们有不同的...
在这个例子中,“path_to_your_asset.dex”是位于Assets目录下的.dex文件路径,我们将其传递给DexClassLoader的构造函数。`getDir("dex", Context.MODE_PRIVATE)`用于创建一个私有的目录来存储优化后的.dex文件,...