java应用程序源代码 java程序源代码文件在哪( 二 )


这为我们编写定制的ClassLoader提供了一条捷径 减少了麻烦 只需覆盖findClass 而不是覆盖loadClass 这种方法避免了重复所有装入器必需执行的公共步骤 因为这一切由loadClass负责
不过 本文的定制ClassLoader并不使用这种方法 原因很简单 如果由默认的ClassLoader先寻找经过加密的类文件 它可以找到;但由于类文件已经加密 所以它不会认可这个类文件 装入过程将失败 因此 我们必须自己实现loadClass 稍微增加了一些工作量
二 定制类装入器
每一个运行着的JVM已经拥有一个ClassLoader 这个默认的ClassLoader根据CLASSPATH环境变量的值 在本地文件系统中寻找合适的字节码文件
应用定制ClassLoader要求对这个过程有较为深入的认识 我们首先必须创建一个定制ClassLoader类的实例 然后显式地要求它装入另外一个类 这就强制JVM把该类以及所有它所需要的类关联到定制的ClassLoader Listing 显示了如何用定制ClassLoader装入类文件
【Listing 利用定制的ClassLoader装入类文件】
以下是引用片段
// 首先创建一个ClassLoader对象 ClassLoader myClassLoader = new myClassLoader(); // 利用定制ClassLoader对象装入类文件 // 并把它转换成Class对象 Class myClass = myClassLoader loadClass( mypackage MyClass ); // 最后 创建该类的一个实例 Object newInstance = myClass newInstance(); // 注意 MyClass所需要的所有其他类 都将通过 // 定制的ClassLoader自动装入
如前所述 定制ClassLoader只需先获取类文件的数据 然后把字节码传递给运行时系统 由后者完成余下的任务
ClassLoader有几个重要的方法 创建定制的ClassLoader时 我们只需覆盖其中的一个 即loadClass 提供获取原始类文件数据的代码 这个方法有两个参数 类的名字 以及一个表示JVM是否要求解析类名字的标记(即是否同时装入有依赖关系的类) 如果这个标记是true 我们只需在返回JVM之前调用resolveClass
【Listing ClassLoader loadClass()的一个简单实现】
以下是引用片段
public Class loadClass( String name boolean resolve ) throws ClassNotFoundException { try { // 我们要创建的Class对象 Class clasz = null; // 必需的步骤 如果类已经在系统缓冲之中 // 我们不必再次装入它 clasz = findLoadedClass( name ); if (clasz != null) return clasz; // 下面是定制部分 byte classData[] = /* 通过某种方法获取字节码数据 */; if (classData != null) { // 成功读取字节码数据 现在把它转换成一个Class对象 clasz = defineClass( name classData classData length ); } // 必需的步骤 如果上面没有成功 // 我们尝试用默认的ClassLoader装入它 if (clasz == null) clasz = findSystemClass( name ); // 必需的步骤 如有必要 则装入相关的类 if (resolveclasz != null) resolveClass( clasz ); // 把类返回给调用者 return clasz; } catch( IOException ie ) { throw new ClassNotFoundException( ie toString() ); } catch( GeneralSecurityException gse ) { throw new ClassNotFoundException( gse toString() ); } }
Listing 显示了一个简单的loadClass实现 代码中的大部分对所有ClassLoader对象来说都一样 但有一小部分(已通过注释标记)是特有的 在处理过程中 ClassLoader对象要用到其他几个辅助方法
findLoadedClass 用来进行检查 以便确认被请求的类当前还不存在 loadClass方法应该首先调用它
defineClass 获得原始类文件字节码数据之后 调用defineClass把它转换成一个Class对象 任何loadClass实现都必须调用这个方法
findSystemClass 提供默认ClassLoader的支持 如果用来寻找类的定制方法不能找到指定的类(或者有意地不用定制方法) 则可以调用该方法尝试默认的装入方式 这是很有用的 特别是从普通的JAR文件装入标准Java类时
resolveClass 当JVM想要装入的不仅包括指定的类 而且还包括该类引用的所有其他类时 它会把loadClass的resolve参数设置成true 这时 我们必须在返回刚刚装入的Class对象给调用者之前调用resolveClass

推荐阅读