- 浏览: 420183 次
- 性别:
- 来自: 济南
文章分类
最新评论
-
pmh905001:
写的很详尽,感谢!
解析jvm.dll和java.exe -
Bll:
插得真深啊,我的是(eclipse_j2ee_juno):F: ...
在eclipse里jsp编译后的java和class文件的位置 -
heming_way:
谢谢,对我很有用,解答了我对多值依赖的疑问
关于多值依赖--范式! -
JavaStudy2011:
java语言解析xml文件 -
vrussell:
Thanks man, it helps me a lot!
获得IEditorPart和IDocument
package com.test.one; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.lang.reflect.Method; public class AutoClassLoader extends ClassLoader { //定义文件所在目录 private static final String DEAFAULTDIR="C:/Documents and Settings/liuzhe.pt/Workspaces/MyEclipse 8.5/test/bin/";; //定义文件绝对路径 private static String FILEPATH=""; /* * 重写ClassLoader类的findClass方法,将一个字节数组转换为 Class 类的实例 */ public Class<?> findClass(String name) throws ClassNotFoundException { System.out.println("----------" + ""); //Class c2=findLoadedClass("com.test.one.tow"); // if(c2==null){ // System.out.println(" ...null"); // // } byte[] b = null; try { b = loadClassData(AutoClassLoader.FormatClassName(name)); } catch (Exception e) { e.printStackTrace(); } System.out.println("findclass-----over"); return defineClass("com.test.one.tow", b, 0, b.length); } private byte[] loadClassData(String filepath) throws Exception { int n =0; BufferedInputStream br = new BufferedInputStream( new FileInputStream( new File(filepath))); ByteArrayOutputStream bos= new ByteArrayOutputStream(); while((n=br.read())!=-1){ bos.write(n); } br.close(); return bos.toByteArray(); } // @Override public Class loadClass(String name){ System.out.println(name);//输出要加载的类!!! System.out.println(name.indexOf("java.")); if(name.indexOf("java.")<5&&name.indexOf("java.")>-1){return null;} Class c2=findLoadedClass("com.test.one.tow"); String path=AutoClassLoader.FormatClassName(name); System.out.println("loadclass"+path); // byte[] b = null; try { b = loadClassData(path); } catch (Exception e) { e.printStackTrace(); } System.out.println("loadclass-----over"+path); return defineClass("com.test.one.tow", b, 0, b.length); } /* * 格式化文件所对应的路径 */ public static String FormatClassName(String name){ FILEPATH= DEAFAULTDIR+name+".class"; return FILEPATH; } /* * main方法测试 */ public static void main(String[] args) throws Exception { AutoClassLoader acl = new AutoClassLoader(); //stem.out.println("-----2-----"); Class c = acl.findClass("com/test/one/tow"); //Object obj = c.newInstance(); //Method m = c.getMethod("getName",new Class[]{String.class ,int.class}); //m.invoke(obj,"你好",123); System.out.println(c.getName()); System.out.println(c.getClassLoader()); System.out.println(c.getClassLoader().getParent()); System.out.println(AutoClassLoader.class.getClassLoader()); } }
这个源码是自定义Classloader的一个类
他定义了loadData()loadClass()findClass()
但如果你运行这个代码的话你会发现 一直报错!他是用自定义的ClassLoader加载
com.test.one.tow(一个简单的类)
说找不到 java.lang.object这个类
当然是在你指定的路径下找不到了!@
怎么出来个 java.lang.object
不知道还记得 加载类的话 他会把所有的父类都要加载一遍 直到java.lang.object
这个实现的方法是在Classloader的loadClass中实现的!
(loadClass是由defineClass1(Native Method)调用的!)
(如果你给tow定义一个父类 你就会发现输出中有加载父类的代码)
你运行了findClass 为什么会运行loadClass呢
因为你在defineClass的时候 他会自动去加载父类的class文件 这些都是Native方法
在Classloader中可以看见!其中会调用loadClass去调用
其中还会调用loadClass去加载
看下报的错误
java.io.FileNotFoundException: C:\Documents and Settings\liuzhe.pt\Workspaces\MyEclipse 8.5\test\bin\java.lang.Object.class (系统找不到指定的文件。) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(Unknown Source) at com.test.one.AutoClassLoader.loadClassData(AutoClassLoader.java:40) at com.test.one.AutoClassLoader.loadClass(AutoClassLoader.java:61) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(Unknown Source) at java.lang.ClassLoader.defineClass(Unknown Source) at java.lang.ClassLoader.defineClass(Unknown Source) at com.test.one.AutoClassLoader.findClass(AutoClassLoader.java:34) at com.test.one.AutoClassLoader.main(AutoClassLoader.java:84) Exception in thread "main" java.lang.NullPointerException at com.test.one.AutoClassLoader.loadClass(AutoClassLoader.java:66) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(Unknown Source) at java.lang.ClassLoader.defineClass(Unknown Source) at java.lang.ClassLoader.defineClass(Unknown Source) at com.test.one.AutoClassLoader.findClass(AutoClassLoader.java:34) at com.test.one.AutoClassLoader.main(AutoClassLoader.java:84)
可以看出 调用了 AutoClassLoader的方法loadClass,然后再往下看又一个ClassLoader的defineClass1 这是一个本地方法!也就是说 defineClass1调用了loadClass的方法 ,但是由于调用方法的对象AutoClassLoader有自定义方法loadClass
所以根据多态性,所以就调用了子类自己的方法!
然而自己的方法显然找不到自己的方法
但是你可以这样写 loadClass!!
public Class loadClass(String name){ System.out.println(name); System.out.println(name.indexOf("java.")); if(name.indexOf("java.")<5&&name.indexOf("java.")>-1){try { //如果是java.开头的交给父类的方法获得Class实例!这样就OK return super.loadClass(name); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }} Class c2=findLoadedClass("com.test.one.tow"); String path=AutoClassLoader.FormatClassName(name); System.out.println("loadclass"+path); // byte[] b = null; try { b = loadClassData(path); } catch (Exception e) { e.printStackTrace(); } System.out.println("loadclass-----over"+path); return defineClass("com.test.one.tow", b, 0, b.length); }
下面是最终执行的defineClass的源码
protected final Class<?> defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) throws ClassFormatError { check(); protectionDomain = preDefineClass(name, protectionDomain); Class c = null; String source = defineClassSourceLocation(protectionDomain); try { c = defineClass1(name, b, off, len, protectionDomain, source);//上面报错的地方//// } catch (ClassFormatError cfe) { c = defineTransformedClass(name, b, off, len, protectionDomain, cfe, source); } postDefineClass(c, protectionDomain); return c; } }
可以看出先要交给父加载器去加载
这时根据多态性,调用loadClass时会使用重写的方法
所以这时加载父类,name成为了java。lang。object
在目录下当然找不到了!!
所以自定义Classloader的时候 不要重写loadClass
大体流程是这样的e
用户自定义findClass
|
|
defineClass
|
|
defineClass1(Native method)
|
|
加载父类
|
|------>调用loadClass加载父类(多态性)
|
----loadClass(用户自定义)(所以如果自定义这个类要把系统类交给 --------------Classloader处理---交给上层的classLoader处理)
|
|
找不到object类
|
|
报错
重写findClass就可以!以免因为加载父类造成异常
另外推荐关于这个的文章
http://tech.sina.com.cn/s/2009-09-02/00351051784.shtml
http://www.cnblogs.com/leo-cnblogs/
或者去我的DBback下载
http://www.dbank.com/download.action?t=40&k=NDc4NjI1MzU=&pcode=LCwxMTI5OTgxLDExMjk5ODE=&rnd=4
- code.rar (1.4 KB)
- 下载次数: 32
发表评论
-
throw 和throws碰到runtimeException
2010-09-02 21:36 38151.throws 用于抛出方法层次的异常, 并且直接由些方法 ... -
Hashtable中的数据结构
2010-08-23 11:38 1131看下Hashtable中的put 方法 public sy ... -
关于StringBuffer的拓展
2010-08-20 16:02 900先访照StringBuffer的append写个类 pub ... -
转帖 精解Classloader
2010-08-18 20:11 969当JVM(Java虚拟机)启动时,会形成由三个类加载器组成的初 ... -
jvm解析多线程
2010-08-18 16:36 1270先看jvm对多线程关于对 ... -
Classloader getResourceAsStream深入
2010-08-17 17:37 1266先写个简单的类 public class Helper { ... -
ClassLoader的基础详解
2010-08-12 13:28 2412java应用环境中不同的class分别由不同的ClassLoa ... -
unicode下的String
2010-07-30 19:34 1098先看一个代码 String o="1" ... -
集合总结
2010-05-31 20:50 1020-集合接口:6个接口(短虚线表示),表示不同集合类型,是集 ... -
自己写的根据unix纪元法 得到时间
2010-05-29 09:46 2009在著名的unix系统中,使用了一种简洁高效的时间表示方法,即: ... -
进阶Enum
2010-05-29 09:42 907先说下enum这个类 private enum Colo ... -
中文转化为unicode
2010-05-28 16:37 1707原文地址: http://www.cnitblog.com/n ... -
构造函数 方法 void 关键字
2010-05-25 22:05 1632public final class Void extends ... -
(转)ConcurrentHashMap实现细节
2010-05-25 16:20 1132原文 http://www.iteye.com/topic/3 ... -
ConcurrentModificationException迭代集合删除元素!!
2010-05-25 14:46 4386ConcurrentModificationException ... -
Checked Exception与Runtime Exception 的区别(转)
2010-04-30 11:03 1191原文:http://www.jspcn.net/h ... -
数组分配的字节码分析
2010-04-25 21:29 1658int [][]a=new int[3][5]; Sys ...
相关推荐
例如,研究ClassLoader的loadClass()方法以及其子类的实现,可以更清晰地了解类加载过程的细节。 8. 工具支持 使用像JConsole、VisualVM这样的工具可以帮助开发者监控类加载情况,分析类加载器的行为,这对于诊断...
- **自定义类加载器**则是通过重写`loadClass`方法来自定义类的加载过程。 ### 总结 本实例展示了如何通过自定义类加载器来加载类并实例化对象的过程。这种方法在某些特定场景下非常有用,比如在需要动态加载类的...
此外,提供的两个PDF文件《Mehlhorn-Sanders-Toolbox.pdf》和《Data Structures and Algorithms.pdf》虽然与Tomcat的ClassLoader直接关联不大,但它们是关于数据结构和算法的重要参考资料。数据结构和算法是软件开发...
Java提供两种动态加载类的方式:隐式加载(通过实例化类)和显式加载(使用`Class.forName()`或`ClassLoader.loadClass()`)。静态块(static block)的执行时机与类的加载密切相关,通常在类被首次加载或实例化时...
例如,`java.lang.ClassLoader`的`loadClass()`方法,以及其子类如`sun.misc.Launcher$AppClassLoader`的实现,可以帮助我们理解双亲委派模型的实现细节。 通过以上内容,我们可以了解到Java类加载器在Java程序运行...
- **`findClass`**:在 JDK 1.2 之后,`loadClass` 方法会默认调用 `findClass` 来实现类的实际加载逻辑。如果自定义的 `ClassLoader` 没有正确实现 `findClass` 方法,则最终会由系统 `ClassLoader` 负责加载。 - *...
1. loadClass(String name):加载名为name的类。它是一个受保护的方法,外界一般通过findClass方法间接调用。 2. findClass(String name):查找并返回名为name的类。这是一个受保护的方法,允许子类覆盖这个方法以...
- 使用`ClassLoader.loadClass(String name)`方法显式加载类。 其中,`Class.forName()`方法有两种重载形式,第一个只接受类名作为参数,第二个允许控制是否初始化类以及指定类加载器。如果只使用一个参数的`Class...
`CSClassLoaderUtil`可能是一个实现了`java.lang.ClassLoader`接口的类,它重写了`loadClass()`方法。这个方法通常用于根据类名查找并加载类。在自定义的类加载器中,我们可以编写代码来从特定的jar包中读取字节码,...
类加载器通过`loadClass()`方法工作,它遵循双亲委派模型:当一个类加载器收到加载类的请求时,它首先会委托给父类加载器去尝试加载,只有当父类加载器无法加载时,当前类加载器才会尝试自己加载。 在实际开发中,...
类加载器的层次结构包括引导类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和系统类加载器(App ClassLoader)。这些内置的类加载器加载的类在JVM生命周期中不会被卸载。而用户自定义的...
- **loadClass**: 这是ClassLoader的核心方法,用于根据类名加载类。它有2个参数,一个是要加载的类名,另一个是一个布尔值,决定是否解析加载的类。 - **defineClass**: 这个方法将字节数组(通常从.class文件...
- 创建自定义类加载器实例后,可以使用`loadClass`方法加载类,并通过`newInstance`方法创建类的实例。 - 示例: ```java NetworkClassLoader loader = new NetworkClassLoader("example.com", 8080); Object ...
- 当`loadClass`方法被调用时,`URLClassLoader`会遍历其URL列表,查找指定类的`.class`文件。 3. **指定目录加载**: - 目录URL(如`file:/path/to/directory/`)用于加载目录下的类文件。类加载器会递归遍历...
- **源码解读**:深入分析`ClassLoader`的核心代码,包括`loadClass`方法等关键部分,掌握类加载过程中的细节。 - **实战案例**:通过具体案例来演示如何利用`ClassLoader`解决实际问题,比如热部署等场景的应用。 ...