`
从此醉
  • 浏览: 1046375 次
  • 性别: Icon_minigender_1
  • 来自: US
社区版块
存档分类
最新评论

自定义类加载器实例(转)

 
阅读更多

虽然在绝大多数情况下,系统默认提供的类加载器实现已经可以满足需求。但是在某些情况下,您还是需要为应用开发出自己的类加载器。比如您的应用通过网络来传输 Java 类的字节代码,为了保证安全性,这些字节代码经过了加密处理。这个时候您就需要自己的类加载器来从某个网络地址上读取加密后的字节代码,接着进行解密和验证,最后定义出要在 Java 虚拟机中运行的类来。下面将通过两个具体的实例来说明类加载器的开发。

下面,详细的介绍自定义一个类加载器的过程。

一、首先,写出一个接口,然后用一个类实现该接口,该类作为测试类,即我们自定义ClassLoader要加载的类。

接口:

复制代码
1 /**
2  * 要加载类的接口,加载该接口的子类时,可以用接口引用,而不需要利用反射来实现。
3  */
4 public interface InterfaceTest {
5     public void name();
6     public void age();
7 }
复制代码

测试类:

复制代码
 1 /**
 2  * 测试类,自定义类加载器去加载该类
 3  */
 4 public class ClassTest implements InterfaceTest{
 5 
 6     @Override
 7     public void name() {
 8         System.out.println("tao");
 9     }
10 
11     @Override
12     public void age() {
13         System.out.println("21");
14     }
15 
16 }
复制代码

二、自定义一个加密类,用来加密测试类的字节码文件。

找到我们要加密的.class文件的位置:E:\workspace.fu\ClassLoaderTest\bin\com\tao\test\ClassTest.class

加密后的.class文件要存储的位置,这里将它直接放到E盘根目录:E:\ClassTest.class

复制代码
 1 /**
 2  * 用加密算法生成要隐藏的字节码文件
 3  */
 4 public class ClassEncrypt extends MyClassLoader{
 5     public static void main(String[] args) throws IOException {
 6         //要加密的字节码.class文件
 7         String srcPath="E:/workspace.fu/ClassLoaderTest/bin/com/tao/test/ClassTest.class";
 8         //加密之后输出的字节码.class文件的位置
 9         String destPath="E:/ClassTest.class";
10         FileInputStream fis=new FileInputStream(srcPath);
11         FileOutputStream ofs=new FileOutputStream(destPath);
12         cypher(fis, ofs);//加密
13         fis.close();
14         ofs.close();
15     }
16     
17     //简单的加密,用于测试。将所有二进制位取反,即0变成1,1变成0
18     private static void cypher(InputStream in,OutputStream out) throws IOException{
19         int b=-1;
20         while((b=in.read())!=-1){
21             out.write(b^0xff);
22         }
23     }
24 }
复制代码

运行该类,那么,我们就已经对ClassTest.class文件加密成功,打开E盘,可以发现根目录下已经有了一个ClassTest.class文件。

可以将E:\workspace.fu\ClassLoaderTest\bin\com\tao\test的ClassTest.class文件删除,并且删除ClassTest.java文件和加密类ClassEncrypt.java。

三、编写我们自己的类加载器,必须继承ClassLoader,然后覆盖findClass()方法。

ClassLoader超类的loadClass方法用于将类的加载操作委托给父类加载器去进行,只有该类尚未加载并且父类加载器也无法加载该类时,才调用findClass()方法。

如果要实现该方法,必须做到以下几点:

(1)、为来自本地文件系统或者其他来源的类加载其字节码

(2)、调用ClassLoader超类的defineClass()方法,向虚拟机提供字节码

复制代码
 1 /**
 2  * 自定义的类加载器
 3  */
 4 public class MyClassLoader extends ClassLoader{
 5     
 6     /**
 7      * 因为类加载器是基于委托机制,所以我们只需要重写findClass方法。
 8      * 它会自动向父类加载器委托,如果父类没有找到,就会再去调用我们重写的findClass方法加载
 9      */
10     @Override
11     protected Class<?> findClass(String name) throws ClassNotFoundException {
12         try {
13             //需要加载的.class字节码的位置
14             String classPath="E:/ClassTest.class";
15             
16             FileInputStream fis=new FileInputStream(classPath);
17             ByteArrayOutputStream bos=new ByteArrayOutputStream();
18             cypher(fis, bos);
19             fis.close();
20             byte[] bytes=bos.toByteArray();
21             return defineClass(bytes, 0, bytes.length);
22         } catch (FileNotFoundException e) {
23             e.printStackTrace();
24         } catch (IOException e) {
25             e.printStackTrace();
26         }
27         return super.findClass(name);
28     }
29     
30     //相应的字节码解密类,在加载E盘根目录下的被加密过的ClassTest.class字节码的时候,进行相应的解密。
31     private static void cypher(InputStream in,OutputStream out) throws IOException{
32         int b=-1;
33         while((b=in.read())!=-1){
34             out.write(b^0xff);
35         }
36     }
37 }
复制代码

四、最后写一个测试类,测试我们的类加载器

复制代码
1 public class Test {
2     public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
3         Class clazz=new MyClassLoader().loadClass("com.tao.test.ClassTest");
4             //这就是我们接口的作用。如果没有接口,就需要利用反射来实现了。
5            InterfaceTest classTest=(InterfaceTest) clazz.newInstance();
6         classTest.name();
7         classTest.age();
8     }
9 }
复制代码

分享到:
评论

相关推荐

    Java语言中的自定义类加载器实例解析

    主要介绍了Java语言中的自定义类加载器实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

    Java实现的自定义类加载器示例

    主要介绍了Java实现的自定义类加载器,结合具体实例形式分析了java自定义类加载器的原理与具体实现技巧,需要的朋友可以参考下

    vb.net 自定义控件(含自定义对话框设置属性) 实例

    vb.net 自定义控件 自定义属性 UITypeEditor UI 类型编辑器 实例 提供一个示例 UITypeEditor,它使用 IWindowsFormsEditorService 显示用于用户输入的 Form。 IWindowsFormsEditorService 只能通过 PropertyGrid ...

    Java虚拟机JVM类加载初始化

    1):本地编译好的class中直接加载 2):网络加载:java.net.URLClassLoader可以加载url指定的类 3):从jar、zip等等压缩文件加载类,自动解析jar文件找到class文件...而由用户自定义的类加载器所加载的类会被卸载掉!

    深入理解java类加载机制

    此外,我们还会探讨Java程序的类加载器和双亲委派机制,以及自定义类加载器和类卸载的实现原理和应用方法。 总的来说,本资源将为Java程序员提供全面的Java字节码和类加载原理和实践经验。通过学习本资源,开发人员将...

    C#开发实例大全(基础卷).软件开发技术联盟(带详细书签) PDF 下载

    实例116 自定义抽象类计算圆形的面积 141 实例117 利用接口实现选择不同的语言 143 实例118 使用密封类密封用户信息 145 实例119 通过重写虚方法实现加法运算 146 实例120 通过类的多态性确定人类的说话 行为 147 ...

    C++Builder精彩编程实例集锦的源代码后3部分.rar

    实例033 如何在状态栏上加载进度条 实例034 如何在编辑框内显示图像 实例035 如何在列表框中增加水平滚动条 实例036 如何在列表框中同时显示图像和文字 实例037 如何设置属性表组件标签图像 实例038 如何控制...

    java范例开发大全

    实例165 自定义复数类 261 9.3 继承 264 实例166 轿车与本田的关系 264 实例167 继承关系的加载顺序 266 实例168 如何访问同名的方法或变量 268 实例169 super()方法的使用 271 实例170 this方法的使用 274 实例171 ...

    Java虚拟机和Java程序的生命周期?

    提供了访问该类在方法去内的数据结构的接口。 类加载有类加载器完成: 类加载器分为:Java虚拟机自带的加载器和用户自定义的类加载器;...用户自定义的类加载器是ClassLoader类的实例,通过它来定制类的加载方式。

    C++Builder精彩编程实例集锦的源代码前3部分.rar

    实例033 如何在状态栏上加载进度条 实例034 如何在编辑框内显示图像 实例035 如何在列表框中增加水平滚动条 实例036 如何在列表框中同时显示图像和文字 实例037 如何设置属性表组件标签图像 实例038 如何控制...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例185 自定义泛型化数组类 235 实例186 泛型方法与数据查询 236 实例187 泛型化方法与最小值 238 实例188 泛型化接口与最大值 239 实例189 使用通配符增强泛型 240 实例190 泛型化的折半查找法 241 第9章 编程常用...

    Java范例开发大全 (源程序)

     实例165 自定义复数类 261  9.3 继承 264  实例166 轿车与本田的关系 264  实例167 继承关系的加载顺序 266  实例168 如何访问同名的方法或变量 268  实例169 super()方法的使用 271  实例170 this...

    java范例开发大全(pdf&源码)

    实例165 自定义复数类 261 9.3 继承 264 实例166 轿车与本田的关系 264 实例167 继承关系的加载顺序 266 实例168 如何访问同名的方法或变量 268 实例169 super()方法的使用 271 实例170 this方法的使用 274 实例171 ...

    java范例开发大全源代码

     实例165 自定义复数类 261  9.3 继承 264  实例166 轿车与本田的关系 264  实例167 继承关系的加载顺序 266  实例168 如何访问同名的方法或变量 268  实例169 super()方法的使用 271  实例170 ...

Global site tag (gtag.js) - Google Analytics