A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

© 王震阳老师   /  2014-8-23 10:40  /  12665 人查看  /  108 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文


good:
  1. package test;

  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.lang.reflect.Method;

  6. public class CompileClassLoader extends ClassLoader{
  7.         //读取一个文件的内容(即Class文件,如Hello.class)
  8.         private byte[] getBytes(String filename) throws IOException{
  9.                 File file = new File(filename);
  10.                 long len = file.length();
  11.                 byte[] raw = new byte[(int)len];
  12.                 FileInputStream fis = null;
  13.                 try{
  14.                         fis = new FileInputStream(file);
  15.                         //一次读取Class文件的全部二进制数据
  16.                         int r = fis.read(raw);
  17.                         if(r != len)
  18.                                 throw new IOException("无法读取全部文件:"+r+"!="+len);
  19.                         return raw;
  20.                 }catch(IOException ioe){
  21.                         throw new RuntimeException("读取文件失败!");
  22.                 }finally{
  23.                         try{
  24.                                 if(fis != null)
  25.                                         fis.close();
  26.                         }catch(IOException ioe){
  27.                                 throw new RuntimeException("读取流关闭失败!");
  28.                         }
  29.                 }
  30.         }
  31.        
  32.         //定义编译指定Java源文件的方法
  33.         private boolean compile(String javaFilename) throws IOException{
  34.                 System.out.println("CompileClassLoader:正在编译"+javaFilename+"...");
  35.                 //调用系统的Javac命令
  36.                 Process p = Runtime.getRuntime().exec("javac "+javaFilename);
  37.                 try{
  38.                         //其它线程都等待这个线程完成
  39.                         p.waitFor();
  40.                 }catch(InterruptedException ie){
  41.                         ie.printStackTrace();
  42.                 }
  43.                 //获取javac线程的退出值
  44.                 int ret = p.exitValue();
  45.                 //返回编译是否成功
  46.                 return ret == 0;
  47.         }
  48.        
  49.         //重写ClassLoader的findClass方法
  50.         protected Class<?> findClass(String name) throws ClassNotFoundException{
  51.                 Class clazz = null;
  52.                 //将包路径中的点(.)替换成斜线(/)
  53.                 String fileStub = name.replace(".", "/");
  54.                 String javaFilename = fileStub+".java";
  55.                 String classFilename = fileStub+".class";
  56.                 File javaFile = new File(javaFilename);
  57.                 File classFile = new File(classFilename);
  58.                
  59.                 //当指定Java源文件存在,且Class文件不存在,
  60.                 //或者java源文件的修改时间比Class文件的修改时间更晚,重新编译
  61.                 if(javaFile.exists() &&(!classFile.exists() || javaFile.lastModified()>classFile.lastModified())){
  62.                         try{
  63.                                 //如果编译失败,或者该Class文件不存在
  64.                                 if(!compile(javaFilename) || !classFile.exists()){
  65.                                         throw new ClassNotFoundException("=============ClassNotFoundException:"+javaFilename);
  66.                                 }
  67.                         }catch(IOException ioe){
  68.                                 ioe.printStackTrace();
  69.                         }
  70.                 }
  71.                 //如果Class文件存在,系统负责将该文件转化成Class对象
  72.                 if(classFile.exists()){
  73.                         try{
  74.                                 //将class文件的二进制数据读入数组
  75.                                 byte[] raw = getBytes(classFilename);
  76.                                 //调用ClassLoader的defineClass方法将二进制数据转换成Class对象
  77.                                 clazz = defineClass(name, raw, 0, raw.length);
  78.                         }catch(IOException ioe){
  79.                                 ioe.printStackTrace();
  80.                         }
  81.                 }
  82.                 //如果clazz为null,表名加载失败,则抛出异常
  83.                 if(clazz == null){
  84.                         throw new ClassNotFoundException(name);
  85.                 }
  86.                 return clazz;
  87.         }
  88.        
  89.         //定义主方法
  90.         public static void main(String[] args) throws Exception{
  91.                 //如果运行该程序(自定义类加载器CompileClassLoader)时没有参数,即没有目标类
  92.                 if(args.length<1){
  93.                         System.out.println("缺少目标类,请按如下格式运行Java源文件:");
  94.                         System.out.println("java CompileClassLoader ClassName");
  95.                         return;
  96.                 }
  97.                 //第一个参数是需要运行的类
  98.                 String progClass = args[0];
  99.                 //剩下的参数将作为运行目标类是的参数
  100.                 //将这些参数复制到一个新数组中
  101.                 String[] progArgs = new String[args.length-1];
  102.                 System.arraycopy(args, 1, progArgs, 0, progArgs.length);
  103.                 CompileClassLoader ccl = new CompileClassLoader();
  104.                 //加载需要运行的类
  105.                 Class<?> clazz = ccl.loadClass(progClass);
  106.                 //获取需要运行的类的主方法
  107.                 Method main = clazz.getMethod("main", (new String[0]).getClass());
  108.                 Object[] argsArray = {progArgs};
  109.                 main.invoke(null, argsArray);
  110.         }
  111. }
复制代码
回复 使用道具 举报
yqj 发表于 2014-8-23 20:04
做完了,交题!

很好:
  1. package cn.test;

  2. import java.io.ByteArrayOutputStream;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.InputStream;
  6. import java.lang.reflect.Constructor;
  7. import java.lang.reflect.Method;
  8. /*
  9. * 为了方便将所有的类写在了个java文件中
  10. * MyClassLoader为自定义的ClassLoader
  11. * TestClass为用来测试类
  12. * ClassLoaderTest为测试类
  13. */

  14. /**
  15. * 自定义的ClassLoader
  16. */
  17. class MyClassLoader extends ClassLoader {
  18.         private String rootDir;

  19.         public MyClassLoader(String rootDir) {
  20.                 this.rootDir = rootDir;
  21.         }

  22.         @Override
  23.         protected Class<?> findClass(String name) throws ClassNotFoundException {
  24.                 byte[] b = getClassData(name);
  25.                 return defineClass(name, b, 0, b.length);
  26.         }
  27.        
  28.         // 读取class字节码为byte数组
  29.         private byte[] getClassData(String name) {
  30.                 if (name == null) {
  31.                         return null;
  32.                 } else {
  33.                         //将name中的"."替换为"/"
  34.                         name = name.replace(".", "/");
  35.                         name=name+".class";
  36.                         try {//将类的class文件读取为byte数组
  37.                                 InputStream in = new FileInputStream(new File(new File(rootDir), name));
  38.                                 ByteArrayOutputStream out = new ByteArrayOutputStream();
  39.                                
  40.                                 byte[] b = new byte[1024];
  41.                                 int len = 0;
  42.                                 while ((len = in.read(b)) != -1) {
  43.                                         out.write(b, 0, len);
  44.                                 }
  45.                                 return out.toByteArray();
  46.                                
  47.                         } catch (Exception e) {
  48.                                 throw new RuntimeException("读取class文件失败!");
  49.                         }
  50.                 }
  51.         }
  52. }

  53. /**
  54. * 用来测试的类
  55. */
  56. class TestClass{
  57.         private void say() {
  58.                 System.out.println("hello world!");
  59.         }
  60. }
  61. /**
  62. *
  63. *测试用自定义的ClassLoad读取TestClass类并运行say()方法
  64. *需要用到反射技术
  65. */
  66. public class ClassLoaderTest {
  67.         public static void main(String[] args) throws Exception {
  68.                 //获取当前类的父地址,由于Class.getResource("")获取的是一个URL,需要切除"file:/"前缀
  69.                 String rootDir=ClassLoaderTest.class.getClassLoader().getResource("").toString();
  70.                 rootDir=rootDir.substring("file:/".length());
  71. //                System.out.println(rootDir);
  72.                 //用自定义的ClassLoad读取TestClass类
  73.                 MyClassLoader classLoader=new MyClassLoader(rootDir);
  74.                 Class<?> clazz=classLoader.findClass("cn.test.TestClass");
  75.                
  76.                 //实例化clazz
  77.                 Constructor<?> c=clazz.getDeclaredConstructor();
  78.                 if(!c.isAccessible()){//暴力反射
  79.                         c.setAccessible(true);
  80.                 }
  81.                 Object o=c.newInstance();
  82.                 //获取clazz的say()方法,并执行
  83.                 Method sayMethod=clazz.getDeclaredMethod("say");
  84.                 if(!sayMethod.isAccessible()){//暴力反射
  85.                         sayMethod.setAccessible(true);
  86.                 }
  87.                 sayMethod.invoke(o);        //打印成功:hello world!
  88.         }
  89. }
复制代码
回复 使用道具 举报 1 0
ximi 中级黑马 2014-8-28 14:02:37
63#
领题了,谢谢了
回复 使用道具 举报
ximi 中级黑马 2014-8-28 16:35:34
64#
阳哥,文件已经已经提交,辛苦啦:D

ClassLoaderTest.zip

1.53 KB, 阅读权限: 200, 下载次数: 1

评分

参与人数 1技术分 +3 收起 理由
王震阳老师 + 3 赞一个!

查看全部评分

回复 使用道具 举报
请查收!

Test3.zip

9.63 KB, 阅读权限: 200, 下载次数: 3

评分

参与人数 1技术分 +3 收起 理由
王震阳老师 + 3 赞一个!

查看全部评分

回复 使用道具 举报

挺好:
  1. package classload;

  2. /**
  3. * @author:
  4. * @date:
  5. * @description:自定义ClassLoader
  6. */
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.FileNotFoundException;
  10. import java.io.IOException;
  11. import java.lang.reflect.InvocationTargetException;
  12. import java.lang.reflect.Method;

  13. public class CompileClassLoader extends ClassLoader {
  14.         // 读入源文件转换为字节数组
  15.         private byte[] getSource(String filename) {
  16.                 File file = new File(filename);
  17.                 int length = (int) file.length();
  18.                 byte[] contents = new byte[length];
  19.                 FileInputStream fis = null;
  20.                 try {
  21.                         fis = new FileInputStream(file);
  22.                         int r = fis.read(contents);
  23.                         if (r != length) {
  24.                                 throw new IOException("IOException:无法读取" + filename);
  25.                         }
  26.                 } catch (FileNotFoundException e) {
  27.                         e.printStackTrace();
  28.                 } catch (IOException e) {
  29.                         e.printStackTrace();
  30.                 } finally {
  31.                         try {
  32.                                 if (fis != null) {
  33.                                         fis.close();
  34.                                 }
  35.                         } catch (IOException e) {
  36.                                 e.printStackTrace();
  37.                         }
  38.                 }
  39.                 return contents;
  40.         }

  41.         // 编译文件
  42.         public boolean compile(String javaFile) {
  43.                 System.out.println("正在编译" + javaFile);
  44.                 int ret = 0;
  45.                 try {
  46.                         // 调用系统命令编译文件
  47.                         Process process = Runtime.getRuntime().exec("javac " + javaFile);
  48.                         process.waitFor();
  49.                         ret = process.exitValue();
  50.                 } catch (IOException e) {
  51.                         e.printStackTrace();
  52.                 } catch (InterruptedException e) {
  53.                         e.printStackTrace();
  54.                 }
  55.                 return ret == 0;
  56.         }

  57.         // 重写findclass
  58.         @Override
  59.         protected Class<?> findClass(String name) throws ClassNotFoundException {
  60.                 Class<?> clazz = null;
  61.                 // 将文件的.替换为/,例如com.lyl.reflect.Reflect被替换为com/lyl/reflect/Reflect
  62.                 String fileStub = name.replace(".", "/");
  63.                 // java源文件名
  64.                 String javaFileName = fileStub + ".java";
  65.                 // 编译后的class文件名
  66.                 String classFileName = fileStub + ".class";
  67.                 File javaFile = new File(javaFileName);
  68.                 File classFile = new File(classFileName);
  69.                 // 当指定JAVA源文件存在,且class文件不存在,
  70.                 // 或者java源文件的修改时间比class文件修改时间晚则重新编译
  71.                 if (javaFile.exists()
  72.                                 && (!classFile.exists() || javaFile.lastModified() > classFile
  73.                                                 .lastModified())) {
  74.                         // 如果编译失败,或者class文件不存在
  75.                         if (!compile(javaFileName) || !classFile.exists()) {
  76.                                 throw new ClassNotFoundException("ClassNotFoundException:"
  77.                                                 + javaFileName);
  78.                         }
  79.                 }
  80.                 // 如果CLASS文件按存在,系统负责将该文件转换成Class对象
  81.                 if (classFile.exists()) {
  82.                         byte[] raw = getSource(classFileName);
  83.                         // 将ClassLoader的defineClass方法将二进制数据转换成Class对象
  84.                         int divindex = name.indexOf("\\");
  85.                         String javafilename = null;
  86.                         // 如果是某个盘里面的文件,要去掉文件的盘符
  87.                         if (divindex != -1) {
  88.                                 javafilename = name.substring(divindex + 1, name.length());
  89.                         }
  90.                         // 将字节数组转换为class实例
  91.                         clazz = defineClass(javafilename, raw, 0, raw.length);
  92.                 }
  93.                 // 如果clazz为null,表明加载失败,则抛出异常
  94.                 if (clazz == null) {
  95.                         throw new ClassNotFoundException(name);
  96.                 }
  97.                 return clazz;
  98.         }

  99.         // 定义主方法
  100.         public static void main(String[] args) throws ClassNotFoundException,
  101.                         SecurityException, NoSuchMethodException, IllegalArgumentException,
  102.                         IllegalAccessException, InvocationTargetException {
  103.                 // 如果运行该程序没有参数,则没有目标类
  104.                 if (args.length < 1) {
  105.                         System.out.println("缺少运行的目标类,请按如下格式运行源文件");
  106.                         System.out.println("java CompileClassLoader ClassName");
  107.                         System.exit(0);
  108.                 }
  109.                 // 第一个参数为需要运行的类
  110.                 String proClass = args[0];
  111.                 // 剩下的参数将作为目标类得参数
  112.                 String[] proArgs = new String[args.length - 1];
  113.                 System.arraycopy(args, 1, proArgs, 0, proArgs.length);
  114.                 CompileClassLoader ccl = new CompileClassLoader();
  115.                 // 加载需要运行的类
  116.                 Class<?> clazz = ccl.loadClass(proClass);
  117.                 Method main = clazz.getMethod("main", (new String[0]).getClass());
  118.                 Object[] argsArray = { proArgs };
  119.                 main.invoke(null, argsArray);
  120.         }
  121. }
复制代码
回复 使用道具 举报
Fengs 中级黑马 2014-8-29 01:56:31
67#
恩恩额!
回复 使用道具 举报
回复回复 领提领题
回复 使用道具 举报
有分送啦!
回复 使用道具 举报
虽然错过了,还是看看题目吧
回复 使用道具 举报
lvc 中级黑马 2014-9-1 03:50:07
71#
看看。。。
回复 使用道具 举报
领题看看
回复 使用道具 举报
看看学习一下。
回复 使用道具 举报
回帖领题~!
回复 使用道具 举报
吊啊.  我也想看看题...
回复 使用道具 举报
看看以前的题目,感受下
回复 使用道具 举报
新手来领题了
回复 使用道具 举报
刚学了这个,来试试
回复 使用道具 举报
做完了,请查收

ClassLoad.rar

1.16 KB, 阅读权限: 150, 下载次数: 1

评分

参与人数 1技术分 +2 收起 理由
王震阳老师 + 2 赞一个!

查看全部评分

回复 使用道具 举报
求技术分
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马