java import自定义类_Java实现的自定义类加载器示例

本文实例讲述了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程序设计有所帮助。

### 回答1: Java自定义类加载器的一个简单的示例代码如下: public class MyClassLoader extends ClassLoader { public Class<?> findClass(String name) { byte[] b = loadClassData(name); return defineClass(name, b, 0, b.length); } private byte[] loadClassData(String name) { // load the class data from the connection } } ### 回答2: Java自定义类加载器代码样例如下: ```java import java.io.*; public class MyClassLoader extends ClassLoader { private String path; // 类加载器加载的路径 public MyClassLoader(String path) { this.path = path; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] data = loadClassData(name); return defineClass(name, data, 0, data.length); } private byte[] loadClassData(String name) { try { FileInputStream fis = new FileInputStream(new File(path + name + ".class")); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int len; while ((len = fis.read()) != -1) { baos.write(len); } fis.close(); return baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return null; } } ``` 使用自定义类加载器加载: ```java public class Main { public static void main(String[] args) throws Exception { MyClassLoader classLoader = new MyClassLoader("加载路径"); Class<?> clazz = classLoader.loadClass("com.example.TestClass"); // 加载TestClass Object obj = clazz.newInstance(); // 创建TestClass实例 // 使用obj进行操作,调用方法等 } } ``` 以上是一个简单的自定义类加载器的代码样例。我们可以根据实际需求,通过自定义类加载器实现更复杂的功能,如加载加密/动态生成的文件,实现文件的热加载等。 ### 回答3: 自定义类加载器是指通过继承ClassLoader并重写其中的方法来实现自己的类加载器。下面是一个简单的Java自定义类加载器的代码示例: ```java import java.io.*; public class MyClassLoader extends ClassLoader { // 自定义类加载器需要指定文件的路径 private String classPath; public MyClassLoader(String classPath) { this.classPath = classPath; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { // 将文件转换成字节流 byte[] data = loadClassData(name); // 调用父的defineClass方法创建对象 return defineClass(name, data, 0, data.length); } private byte[] loadClassData(String className) { try { // 文件的完整路径 String path = classPath + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; InputStream inputStream = new FileInputStream(new File(path)); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; // 读取文件并写入内存中 while ((length = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, length); } inputStream.close(); outputStream.close(); // 返回字节流 return outputStream.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return null; } public static void main(String[] args) { // 实例化自定义类加载器并指定文件路径 MyClassLoader classLoader = new MyClassLoader("路径"); try { // 使用自定义类加载器加载 Class<?> clazz = classLoader.loadClass("名"); // 可以对加载的进行操作 // ... } catch (ClassNotFoundException e) { e.printStackTrace(); } } } ``` 这个自定义类加载器首先需要重写`findClass`方法,在该方法中通过`loadClassData`方法将文件读取为字节流,然后调用父的`defineClass`方法创建对象。 `loadClassData`方法根据指定的文件路径将文件读取为字节流,并将字节流写入ByteArrayOutputStream中,最后返回字节数组。 在示例代码的`main`方法中,实例化自定义类加载器并指定文件路径,然后通过`loadClass`方法加载指定的。可以在加载后对其进行相关操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值