本文实例讲述了Java实现的自定义类加载器。分享给大家供大家参考,具体如下:

一 点睛

1 ClassLoader类有如下两个关键方法:

loadClass(String name, boolean resolve):该方法为ClassLoader的入口点,根据指定的二进制名称来加载类,系统就是调用ClassLoader的该方法来获取指定类对应的Class对象。

findClass(String name):根据二进制名称来查找类。

如果需要实现自定义的ClassLoader,可以通过重写以上两个方法来实现,当然我们推荐重写findClass()方法,而不是重写loadClass()方法。

2 自定义类加载器常用功能

执行代码前自动验证数字签名。

根据用户提供的密码解密代码,从而可以实现代码混淆器来避免反编译class文件。

根据用户需求来动态地加载类。

根据应用需求把其他数据以字节码的形式加载到应用中。

二 实战

1 CompileClassLoader.java

import java.io.*;

import java.lang.reflect.*;

public class CompileClassLoader extends ClassLoader

{

// 读取一个文件的内容

private byte[] getBytes(String filename)

throws IOException

{

File file = new File(filename);

long len = file.length();

byte[] raw = new byte[(int)len];

try(

FileInputStream fin = new FileInputStream(file))

{

// 一次读取class文件的全部二进制数据

int r = fin.read(raw);

if(r != len)

throw new IOException("无法读取全部文件:"

+ r + " != " + len);

return raw;

}

}

// 定义编译指定Java文件的方法

private boolean compile(String javaFile)

throws IOException

{

System.out.println("CompileClassLoader:正在编译 "

+ javaFile + "...");

// 调用系统的javac命令

Process p = Runtime.getRuntime().exec("javac " + javaFile);

try

{

// 其他线程都等待这个线程完成

p.waitFor();

}

catch(InterruptedException ie)

{

System.out.println(ie);

}

// 获取javac线程的退出值

int ret = p.exitValue();

// 返回编译是否成功

return ret == 0;

}

// 重写ClassLoader的findClass方法

protected Class> findClass(String name)

throws ClassNotFoundException

{

Class clazz = null;

// 将包路径中的点(.)替换成斜线(/)。

String fileStub = name.replace("." , "/");

String javaFilename = fileStub + ".java";

String classFilename = fileStub + ".class";

File javaFile = new File(javaFilename);

File classFile = new File(classFilename);

// 当指定Java源文件存在,且class文件不存在、或者Java源文件

// 的修改时间比class文件修改时间更晚,重新编译

if(javaFile.exists() && (!classFile.exists()

|| javaFile.lastModified() > classFile.lastModified()))

{

try

{

// 如果编译失败,或者该Class文件不存在

if(!compile(javaFilename) || !classFile.exists())

{

throw new ClassNotFoundException(

"ClassNotFoundExcetpion:" + javaFilename);

}

}

catch (IOException ex)

{

ex.printStackTrace();

}

}

// 如果class文件存在,系统负责将该文件转换成Class对象

if (classFile.exists())

{

try

{

// 将class文件的二进制数据读入数组

byte[] raw = getBytes(classFilename);

// 调用ClassLoader的defineClass方法将二进制数据转换成Class对象

clazz = defineClass(name,raw,0,raw.length);

}

catch(IOException ie)

{

ie.printStackTrace();

}

}

// 如果clazz为null,表明加载失败,则抛出异常

if(clazz == null)

{

throw new ClassNotFoundException(name);

}

return clazz;

}

// 定义一个主方法

public static void main(String[] args) throws Exception

{

// 如果运行该程序时没有参数,即没有目标类

if (args.length < 1)

{

System.out.println("缺少目标类,请按如下格式运行Java源文件:");

System.out.println("java CompileClassLoader ClassName");

}

// 第一个参数是需要运行的类

String progClass = args[0];

// 剩下的参数将作为运行目标类时的参数,

// 将这些参数复制到一个新数组中

String[] progArgs = new String[args.length-1];

System.arraycopy(args , 1 , progArgs

, 0 , progArgs.length);

CompileClassLoader ccl = new CompileClassLoader();

// 加载需要运行的类

Class> clazz = ccl.loadClass(progClass);

// 获取需要运行的类的主方法

Method main = clazz.getMethod("main" , (new String[0]).getClass());

Object[] argsArray = {progArgs};

main.invoke(null,argsArray);

}

}

2 Hello.java

public class Hello

{

public static void main(String[] args)

{

for (String arg : args)

{

System.out.println("运行Hello的参数:" + arg);

}

}

}

3 运行

E:\Java\疯狂java讲义\codes\18\18.2>java CompileClassLoader Hello 自定义加载器

CompileClassLoader:正在编译 Hello.java...

运行Hello的参数:自定义加载器

希望本文所述对大家java程序设计有所帮助。

java import自定义类_Java实现的自定义类加载器示例相关推荐

  1. java 线程加载类_java JVM-线程上下类加载器

    public class One { public static void main(String[] args) throws Exception { ClassLoader loader=One. ...

  2. java 虚拟机内存类_java 虚拟机类加载 及内存结构

    在面试java工程师的时候,这道题经常被问到,故需特别注意. 1.JVM 简介 JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从"Hello World &q ...

  3. delphi7 获取dll的类_跟我学Java内存管理----JMM精华终章(类加载器)

    1 类加载器 1.1 类的加载过程 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. (1)加载 就是指将class文件读入内存,并为之创 ...

  4. java反射 数组类,乐字节Java反射之三:方法、数组、类加载器和类的生命周期

    继续讲述Java反射之三:方法.数组.类加载器 一.方法 获取所有方法(包括父类或接口),使用Method即可. public static void test() throwsException { ...

  5. Java基础加强-(注解,动态代理,类加载器,servlet3.0新特性)

    1.   Annotation注解 1.1.  Annotation概述 Annotation是JDK 5.0以后提供对元数据的支持,可以在编译.加载和运行时被读取,并执行相应的处理.所谓Annota ...

  6. Flex 序列化自定义类 解决 sharedObject 保存自定义对象

    问题 我想把自定义类实例存储到LSO 解决办法 使用flash.net.registerClassAlias( )方法保留类型信息并把类实例添加到共享对象的data属性上. 讨论 LSOs 使用特殊的 ...

  7. java原子更新类_Java内部具有原子更新的动态热交换环境

    java原子更新类 有人可能会争辩说上述标题可以简称为OSGi ,我想在一开始就放弃这种思考过程. 对于OSGi而言,这没有什么冒犯的,它是一个很棒的规范,在实现层或可用性层上都搞砸了,这就是我对OS ...

  8. android studio自定义类,为AndroidStudio设置自定义类注释

    我们在使用eclipse的时候,只要在类上面输入/**再按enter,就会出现类注释. package com.demo; /** * * @author chenjunxu * */ public ...

  9. java mysql 操作类_Java 数据库简单操作类

    1 packagecom.latiny.db;2 3 import java.io.*;4 import java.sql.*;5 importjava.util.ArrayList;6 import ...

最新文章

  1. EM算法讲推导原理讲的懂了的,表达清晰易懂的, 收藏cnblog上的大牛的
  2. 关联本地git仓库与Github仓库
  3. MySql 内连接,外连接查询方式区别
  4. Mqtt协议IOS端移植3
  5. 【C语言】(for循环嵌套)找出1000以内的水仙花数
  6. 开源的电信堆栈软件 FreeSwitch 中存在五个漏洞
  7. STM32:GPIO四种输入输出模式。
  8. 【miscellaneous】语音识别工具箱综述和产品介绍
  9. 2018阿里-研发工程师JAVA Software Engineer, Java
  10. Emacs代码补全之ycmd
  11. 调用css样式是不调用某个属性,CSS选择器可以引用另一个选择器属性吗?
  12. 高雅复古立式钢琴音源 Native Instruments The Gentleman Kontakt
  13. 支持嵌入的手机号码识别sdk软件
  14. rpm -ivh安装mysql_rpm的用法 详解
  15. 错误的SQL脚本,错误消息 4104
  16. python爬取知乎热搜_python爬取知乎
  17. fseek,ftell,rewind函数
  18. cocos creator经典游戏英文版《俄罗斯方块》源码H5+安卓+IOS三端源码
  19. 135、易燃液体的火灾危险性
  20. centos7局域网挂载nas硬盘

热门文章

  1. MTK方案下tee.img的打包方式的详细拆解
  2. MySQL的索引及优化方案
  3. Git安装以及操作过程
  4. 2020-12-4((ARM汇编)mov指令,LDR指令,LDR伪指令)
  5. 1.1 Java异常(Exception)处理及常见异常
  6. 1.11 Lambda表达式遍历Iterator迭代器
  7. 验证字符串是否以指定字符开头
  8. Python多进程之构建进程池
  9. 第三章 图论【未完成】
  10. C语言希尔排序(解析)