自定义ClassLoader
来源:互联网 发布:java多线程同步和死锁 编辑:程序博客网 时间:2024/05/11 23:39
最近在做一个工作,把两个文件合并,Android中的两个R.java文件合并。看到这个需求时,想到两种方法: 1)逐行读文件,根据关键字区分哪些是内部类,哪些是内部类的成员变量;2)通过将.java文件编译并加载,通过反射得到内部类,和成员变量。第二种方法更直接一些,本文记录下编译并加载.java文件的方法和问题。
目的:编译并加载磁盘上任意位置的.java文件。
实现MyClassloader,继承自ClassLoader,重写findClass方法
package com.demo.RMerger;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;public class MyClassloader extends ClassLoader {private String mPre;public MyClassloader(String pre) {mPre = pre;}// 读取一个文件的内容private byte[] getBytes(String filename) throws IOException {FileInputStream fi = null;fi = new FileInputStream(filename);ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[8192];int read;while ((read = fi.read(buffer)) > 0)baos.write(buffer, 0, read);byte[] classBytes = baos.toByteArray();return classBytes;}// 定义编译指定Java文件的方法public boolean compile(String javaFile) throws IOException {System.out.println("CompileClassLoader:正在编译" + javaFile + "...");// 调用系统的javac命令Process p = Runtime.getRuntime().exec("javac " + javaFile);try {p.waitFor();} catch (InterruptedException e) {e.printStackTrace();}// 获取javac线程的退出值int ret = p.exitValue();// 返回编译是否成功return ret == 0;}// 重写ClassLoader的findClass方法protected Class<?> findClass(String name) throws ClassNotFoundException {Class clazz = null;// 将包路径中的点替换成斜线String fileStub = name.replace(".", File.separator);String javaFilename = mPre + fileStub + ".java";String classFilename = mPre + fileStub + ".class";File javaFile = new File(javaFilename);File classFile = new File(classFilename);if (javaFile.exists() && (!classFile.exists()|| javaFile.lastModified() > classFile.lastModified())) {try {// 如果编译失败,或者该Class文件不存在if (!compile(javaFilename) || !classFile.exists()) { // 这一步compile重新编译了一次throw new ClassNotFoundException("ClassNotFoundException:" +javaFilename);}} catch (IOException e) {e.printStackTrace();}}// 如果Class文件存在,系统负责将该文件转换成Class对象if (classFile.exists()) {try {// 将Class文件的二进制数据读入数组byte[] raw = getBytes(classFilename);// 调用ClassLoader的defineClass方法将二进制数据成Class对象clazz = defineClass(name, raw, 0, raw.length);} catch (IOException e) {e.printStackTrace();}}// 如果clazz为null,则表明加载失败,抛出异常if (clazz == null) {throw new ClassNotFoundException(name);}return clazz;}}调用方法:
MyClassloader myClassloader = new MyClassloader(System.getProperty("user.dir") + File.separatorChar + pre+ File.separatorChar);
Class<?> R = myClassloader.loadClass(name.replace(File.separatorChar, '.'));
注意调用loadClass时候需要用包名+类名;比如com.android.R。
System.getProperty("user.dir")表示当前工程的路径。
0 0
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- Java_ClassLoader(ClassLoader / 自定义ClassLoader / DexClassLoader)
- 自定义一个ClassLoader.
- 自定义EclipsePlugin ClassLoader (2)
- 自定义classloader的实现
- 自定义ClassLoader 简单例子
- java 自定义ClassLoader
- 自定义ClassLoader类
- 自定义 Java ClassLoader
- 自定义ClassLoader解析
- Schema
- E437: terminal capability "cm" required 错误出现的原因和解决方法
- Linux Wait Queue and Completion Summary
- hdu 1059/ poj 1014 多重背包
- SQLite3中的日期时间函数使用小结
- 自定义ClassLoader
- EXT JS5学习之Sencha Cmd下载安装
- android学习01
- hdu 5044 树链剖分+前缀和
- requirejs 简单用法
- 交换两个变量的值
- window查找指定字符串在当前目录下的所有文件中是否存在
- IO模型之IO多路复用
- 如何对一张图片打Tag标签