|
如何有效防止Java程序源码被人偷窥(2) // 利用定制ClassLoader对象装入类文件 // 并把它转换成Class对象 Class myClass = myClassLoader.loadClass( "mypackage.MyClass" ); // 最后,创建该类的一个实例 Object newInstance = myClass.newInstance(); // 注意,MyClass所需要的所有其他类,都将通过 // 定制的ClassLoader自动装入
如前所述,定制ClassLoader只需先获取类文件的数据,然后把字节码传递给运行时系统,由后者完成余下的任务。
ClassLoader有几个重要的方法。创建定制的ClassLoader时,我们只需覆盖其中的一个,即loadClass,提供获取原始类文件数据的代码。这个方法有两个参数:类的名字,以及一个表示JVM是否要求解析类名字的标记(即是否同时装入有依赖关系的类)。如果这个标记是true,我们只需在返回JVM之前调用resolveClass。
【Listing 2:ClassLoader.loadClass()的一个简单实现】
public Class loadClass( String name, boolean resolve ) throws ClassNotFoundException { try { // 我们要创建的Class对象 Class clasz = null; // 必需的步骤1:如果类已经在系统缓冲之中, // 我们不必再次装入它 clasz = findLoadedClass( name ); if (clasz != null) return clasz; // 下面是定制部分 byte classData[] = /* 通过某种方法获取字节码数据 */; if (classData != null) { // 成功读取字节码数据,现在把它转换成一个Class对象 clasz = defineClass( name, classData, 0, classData.length ); } // 必需的步骤2:如果上面没有成功, // 我们尝试用默认的ClassLoader装入它 if (clasz == null) clasz = findSystemClass( name ); // 必需的步骤3:如有必要,则装入相关的类 if (resolve && clasz != null) resolveClass( clasz ); // 把类返回给调用者 return clasz; } catch( IOException ie ) { throw new ClassNotFoundException( ie.toString() ); } catch( GeneralSecurityException gse ) { throw new ClassNotFoundException( gse.toString() );
|