第一步:  给你一个编译好的class文件以及它的包名,创建一个对象出来。

1)class文件源代码

  1. package com.wsc.classloader;
  2. public class Tool{
  3. public void print() {
  4. }
  5. }

2)使用javac Tool.java 编译成class文件

3)将Tool.class文件读取到内存中,生成byte[]数组

  1. /**
  2. * 加载class文件
  3. *
  4. * @param clazzPath
  5. *            class绝对文件路径
  6. * @return 字节数组
  7. * @throws IOException
  8. */
  9. private byte[] loadClassFile(String clazzPath) throws IOException {
  10. FileInputStream fis = new FileInputStream(clazzPath);
  11. BufferedInputStream bis = new BufferedInputStream(fis);
  12. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  13. byte[] buffer = new byte[1024 * 256];
  14. int ch = 0;
  15. while ((ch = bis.read(buffer, 0, buffer.length)) != -1) {
  16. baos.write(buffer, 0, ch);
  17. }
  18. return baos.toByteArray();
  19. }

4)自定义ClassLoader,使用ClassLoader中的defineClass方法:protected final Class<?> defineClass(String name, byte[] b, int off, int len)。参数分别是类名称,class文件对应的字节数组,起始位置和终止位置。

  1. @Override
  2. protected Class<?> loadClass(String name, boolean resolve)
  3. throws ClassNotFoundException {
  4. Class<?> c = findLoadedClass(name);
  5. if (c == null) {
  6. c = defineClass(name, data, 0, data.length);
  7. }
  8. return c;
  9. }

整体代码是:

  1. package com.wsc.classloader;
  2. import java.io.BufferedInputStream;
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.FileInputStream;
  5. import java.io.IOException;
  6. public class ClassLoaderOne extends ClassLoader {
  7. public static void main(String[] args) throws Exception {
  8. ClassLoaderOne loader = new ClassLoaderOne(
  9. "E:\\JAVA\\JAVAFX\\ClassLoader\\libs\\Tool.class");
  10. Class<?> clazz = loader.loadClass("com.wsc.classloader.Tool");
  11. Object o = clazz.newInstance();
  12. System.out.println(o.getClass().getClassLoader());
  13. }
  14. private byte[] data;
  15. public ClassLoaderOne(String clazzPath) throws IOException {
  16. data = loadClassFile(clazzPath);
  17. }
  18. /**
  19. * 加载class文件
  20. *
  21. * @param clazzPath
  22. *            class绝对文件路径
  23. * @return 字节数组
  24. * @throws IOException
  25. */
  26. private byte[] loadClassFile(String clazzPath) throws IOException {
  27. FileInputStream fis = new FileInputStream(clazzPath);
  28. BufferedInputStream bis = new BufferedInputStream(fis);
  29. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  30. byte[] buffer = new byte[1024 * 256];
  31. int ch = 0;
  32. while ((ch = bis.read(buffer, 0, buffer.length)) != -1) {
  33. baos.write(buffer, 0, ch);
  34. }
  35. return baos.toByteArray();
  36. }
  37. @Override
  38. protected Class<?> loadClass(String name, boolean resolve)
  39. throws ClassNotFoundException {
  40. Class<?> c = findLoadedClass(name);
  41. if (c == null) {
  42. c = defineClass(name, data, 0, data.length);
  43. }
  44. return c;
  45. }
  46. }

感觉是这样的,跑一下:

  1. Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang
  2. at java.lang.ClassLoader.preDefineClass(Unknown Source)
  3. at java.lang.ClassLoader.defineClass(Unknown Source)
  4. at java.lang.ClassLoader.defineClass(Unknown Source)
  5. at com.wsc.classloader.ClassLoaderOne.loadClass(ClassLoaderOne.java:52)
  6. at java.lang.ClassLoader.loadClass(Unknown Source)
  7. at java.lang.ClassLoader.defineClass1(Native Method)
  8. at java.lang.ClassLoader.defineClass(Unknown Source)
  9. at java.lang.ClassLoader.defineClass(Unknown Source)
  10. at com.wsc.classloader.ClassLoaderOne.loadClass(ClassLoaderOne.java:52)
  11. at java.lang.ClassLoader.loadClass(Unknown Source)
  12. at com.wsc.classloader.ClassLoaderOne.main(ClassLoaderOne.java:14)

意思是:禁止加载名为java.lang的包。

原因是:虽然Tool类中没有使用任何引入java.lang下类,但是它的父类Object是在java.lang下的,classloader加载Tool类时会把它所有的关系网都加载出来才行,父类Object肯定是要加载的。

这样就简单了!无非多写一个If else.使用父加载器(类加载器都有一个父类加载器)加载即可。

  1. @Override
  2. protected Class<?> loadClass(String name, boolean resolve)
  3. throws ClassNotFoundException {
  4. Class<?> c = findLoadedClass(name);
  5. if (name.equals("java.lang.Object")) {
  6. ClassLoader parent = getParent();
  7. c = parent.loadClass(name);
  8. }
  9. if (c == null) {
  10. c = defineClass(name, data, 0, data.length);
  11. }
  12. return c;
  13. }

跑一下结果是:

  1. com.wsc.classloader.ClassLoaderOne@ca470

第二步:新的问题

  1. Method[] methods = clazz.getMethods();
  2. for (int i = 0; i < methods.length; i++) {
  3. String name = methods[i].getName();
  4. System.out.println(name);
  5. Class<?>[] params = methods[i].getParameterTypes();
  6. for (int j = 0; j < params.length; j++) {
  7. System.out.println(params[j].toString());
  8. }
  9. }

这个时候还是会报刚才的错误,因为Method类也在java.lang包下,只能在增加一个If else.

显然,代码应该这样写

  1. @Override
  2. protected Class<?> loadClass(String name, boolean resolve)
  3. throws ClassNotFoundException {
  4. Class<?> c = findLoadedClass(name);
  5. if (c == null) {
  6. // 如果父加载器不为null,使用父类加载器加载(比如Object,HashMap等核心类)
  7. if (getParent() != null) {
  8. try {
  9. c = getParent().loadClass(name);
  10. } catch (Exception e) {
  11. // 父类可能没加载,则抛异常
  12. }
  13. }
  14. // 如果父类加载器没有加载,再使用自定义加载器加载
  15. if (c == null) {
  16. c = defineClass(name, data, 0, data.length);
  17. }
  18. }
  19. return c;
  20. }

打印结果:

  1. toString
  2. print
  3. class java.lang.String
  4. getClass
  5. hashCode
  6. equals
  7. class java.lang.Object
  8. notify
  9. notifyAll
  10. wait
  11. long
  12. int
  13. wait
  14. wait
  15. long
  16. com.wsc.classloader.ClassLoaderOne@fcfa52

第三步:如果本地可以通过.class文件创建,远程当然也已同一个道理(如果需要加密,在本地多一个解密即可)。如果class文件是远程调用的话,本地一般使用接口或者反射两种方法调用。首选是接口,反射一是效率,而是要清楚所有的方法名称、参数名称过于麻烦。

由于远程加载class文件到本地,如果出错很难定位出错位置。幸好,classloader使用规则默认是根据URLClassLoader来使用的,会先根据检查本地是否有该类,所以可以直接将源码放在本地即可调试,当然发布的时候一定要删除。

如图:

    通过这个基本的入门程序可以了解ClassLoader的基本流程。

1

用.class文件创建对象的更多相关文章

  1. 大三上 —— IOS五天实训

    第二天: 注册使用xib:1.首先为xib文件创建对象--let nib = UINib(nibName: "xib文件名", bundle: nil).2.具体的控件注册该xib ...

  2. xib与nib的区别

    xib和nib都是Interface Builder的图形界面设计文档,nib这个名字来自于NeXTSTEP系统,在NeXTSTEP被Apple收购之前,一直使用nib作为Interface Buil ...

  3. 十七、EnterpriseFrameWork框架核心类库之Web控制器

    回<[开源]EnterpriseFrameWork框架系列文章索引> EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U EFW框架中的WebContro ...

  4. VBS基础篇 - wscript 对象

    一.wscript对象 描述:提供对 Windows 脚本宿主对象模型根对象的访问.详述:WScript 对象是 Windows 脚本宿主对象模型层次结构的根对象.它可在任何脚本文件中使用,不需要特定 ...

  5. 【转】基于RMAN实现坏块介质恢复(blockrecover)

    本文转自:乐沙弥的世界 对于物理损坏的数据块,我们可以通过RMAN块介质恢复(BLOCK MEDIA RECOVERY)功能来完成受损块的恢复,而不需要恢复整个数据库或所有文件来修复这些少量受损的数据 ...

  6. java反射知识

    java反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称 ...

  7. 我用Cocos2d-x模拟《Love Live!学院偶像祭》的Live场景(二)

    上一章分析了Live场景中各个元素的作用,这一章开始来分析最关键的部分——打击物件的实现. 上一章放出的视频很模糊,先来看一个清晰版的复习一下:http://www.bilibili.com/vide ...

  8. 【Unity 3D 游戏开发】Unity3D 入门 - 工作区域介绍 与 入门示例

    一. 工作区域详解 1. Scence视图 (场景设计面板) scence视图简介 : 展示创建的游戏对象, 可以对所有的游戏对象进行 移动, 操作 和 放置; -- 示例 : 创建一个球体, 控制摄 ...

  9. OC语言大总结(上)

    根据OC学习的知识点,总结了一下,希望能帮到大家! 作者:韩俊强  未经允许,请勿转载! 关注博主:http://weibo.com/hanjunqiang 第一节类于对象   类与对象http:// ...

随机推荐

  1. 解决SDK Manager无法更新问题

    因为google被封了,导致Android SDK Manager无法更新,解决方案如下: 1.选择tools->options,跳出Settings页面 2.设置HTTP Proxy代理,设置 ...

  2. 获取Ip 的地域等信息接口-实例

    今天项目要用到 查询访问网站用户的IP 然后网上查询了 资料还很多 不过有些已经失效了 在这总结下 腾讯,pconline 的API已经失效 不能使用 淘宝的IP接口地址: http://ip.tao ...

  3. Android Linux自带iptables配置IP访问规则

    利用Linux自带iptables配置IP访问规则,即可做到防火墙效果

  4. How to install Pygame for Python 3.4 on Ubuntu 14.04(转)

    First run this to install dependencies: sudo apt-get install mercurial python3-dev python3-numpy \ l ...

  5. Xcode 插件开发

    我最近一年来都在开发ios应用,不过感觉公司的app维护起来非常麻烦. 因为公司要为很多个企业订做app,每个app的功能基本相同,只是界面上的一些图片和文字要换掉,功能也有一些小改动.考虑到代码维护 ...

  6. 使用token机制来验证用户的安全性-b

    登录的业务逻辑{    http:是短连接.         服务器如何判断当前用户是否登录?        // 1. 如果是即时通信类:长连接.    // 如何保证服务器跟客户端保持长连接状态? ...

  7. Codeforces Round #Pi (Div. 2)

    上次比完赛就准备写了, 结果懒癌发作了, 拖到了现在. Problem_A: 题意: 在一条x轴上有n座城市, 每个城市之间的距离就是它们对应坐标的距离, 现在求出每个城市到其他城市的最近距离和最远距 ...

  8. vbox里面的Ubuntu虚拟机与主机win7之间设置共享文件夹

    有时候我们希望虚拟机和主机之间进行通信,例如传一些文件.那么设置共享文件夹就是一种很好的方式. 这里我的主机是win7系统,vbox里面的虚拟机是Ubuntu. 1.首先安装vbox的VBOXGues ...

  9. Hibernate中的一对一关系详解(1)

    A:先讲讲一对一的关系(欲知其他关系,请看下篇) a:主键关联的一对一关系 一对一关系一般用主键关联,也就是说用主键值来维护两者的关系,一个表的主键存放另一个表的主键值.例如在员工与帐号中,我们取员工 ...

  10. 上网必备AdBlock,远离广告!

    浏览器广告拦截插件,绝对上网必备... 从此告别讨厌的百度边栏广告!!! https://getadblock.com/ https://adblockplus.org/zh_CN/