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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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

第一次领题。
回复 使用道具 举报
看题                              
回复 使用道具 举报
只为头排,努力抢沙发!
回复 使用道具 举报
回帖取题
回复 使用道具 举报
回复看看题目
回复 使用道具 举报
赞一个!
回复 使用道具 举报
这2期的技术分活动相距很近哦
回复 使用道具 举报
有这活动真好
回复 使用道具 举报
领题了。。。。
回复 使用道具 举报
没沙发,板凳好硬
回复 使用道具 举报
我来领题了。
回复 使用道具 举报
不得不说  做这个题目之前 我听都没有听说过ClassLoader   建议阳阳哥每次当期技术分活动结束以后  放开相应附件的下载权限 这样大家可以观摩学习下

src.zip

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

ClassLoader技术分

评分

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

查看全部评分

回复 使用道具 举报
学完,敲完,递交完,洗洗睡了

MyClassLoader.rar

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

类加载器、反射

评分

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

查看全部评分

回复 使用道具 举报
领题看看。
回复 使用道具 举报
孙小亚 发表于 2014-8-23 21:24
来提交啦!我是写了三个java文件,放在一个文件夹里面,阳哥辛苦了。。。
...

可以:
  1. package com.itheima.loadertest;
  2. /**
  3. * 自定义一个类加载器,并且通过该类加载器加载一个类源码,并且运行改类中的一个方法。
  4. * @author Sunzy
  5. *
  6. */
  7. import java.io.*;

  8. public class MyClassLoader extends ClassLoader{
  9.         private String name;
  10.         // 通过这个构造方法生成的类加载器,它的父加载器是系统类加载器  
  11.     public MyClassLoader(String name) {  
  12.         super();
  13.         this.name = name;  
  14.     }
  15.     // 通过这个这个构造方法生成的类加载器,该加载器的父加载器是loader,如果为空,则父加载器为根加载器
  16.     public MyClassLoader(String name, ClassLoader loader) {  
  17.         super(loader);   
  18.         this.name = name;  
  19.     }
  20.     // 要重写findclass这个方法
  21.     @Override
  22.         protected Class<?> findClass(String name) throws ClassNotFoundException {
  23.             byte[] data = null;  
  24.         FileInputStream fis = null;  
  25.        try {  
  26.            fis = new FileInputStream("E:\\workspace_Android\\DailyTest1\\bin\\com\\itheima\\loadertest\\"+name+".class");  
  27.        } catch (FileNotFoundException e) {  
  28.            System.out.println(e);  
  29.        }  
  30.         ByteArrayOutputStream abos = new ByteArrayOutputStream();  
  31.         int ch = 0;  
  32.         try {  
  33.            while ((ch=fis.read()) != -1)  {  
  34.                  abos.write(ch);        //把字节一个一个写到输出流中  
  35.             }  
  36.        } catch (IOException e) {  
  37.            e.printStackTrace();  
  38.        }  
  39.         data = abos.toByteArray();   //把输出流中的字节弄成一个字节数组  
  40.        return this.defineClass("com.itheima.loadertest."+name,data, 0, data.length,null);  
  41.     }                
  42.        
  43.         public String toString()  
  44.     {  
  45.         return this.name;  
  46.     }  
  47.    
  48. }
复制代码
回复 使用道具 举报
SmallRooker 发表于 2014-8-23 21:21
老师交题,虽然有些不明白 ,还有一些是抄袭了本吧里的代码。写好几遍了。已经记住原理了,现在正在刻苦学 ...

能学到东西就行,不过你怎么把文件解压的代码提交了,这个模块提交的自定义类加载器呀?
回复 使用道具 举报

挺好:
  1. package com.cn.brainfreeze;

  2. import java.io.BufferedInputStream;
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.FileInputStream;
  5. import java.io.FileNotFoundException;
  6. import java.io.IOException;
  7. import java.lang.reflect.Method;

  8. //自定义类加载器
  9. public class MyClassLoader extends ClassLoader{
  10.         //定义两个成员变量,表示类加载器的名字与欲加载类的父路径
  11.         private String name;
  12.         private String path;
  13.        
  14.         //让系统类加载器成为该类加载器的父级类加载器
  15.         public MyClassLoader(String name) {
  16.                 super();
  17.                 this.name=name;
  18.         }
  19.         //让给定的类加载器成为该类加载器的父级类加载器
  20.         public MyClassLoader(ClassLoader parent,String name) {
  21.                 super(parent);
  22.                 this.name=name;
  23.         }
  24.        
  25.         //name与path的getter与setter方法
  26.         public String getName() {
  27.                 return name;
  28.         }
  29.         public void setName(String name) {
  30.                 this.name = name;
  31.         }
  32.         public String getPath() {
  33.                 return path;
  34.         }
  35.         public void setPath(String path) {
  36.                 this.path = path;
  37.         }
  38.        
  39.         //重写findClass方法,使其加载指定目录的class文件
  40.         @Override
  41.         @SuppressWarnings("deprecation")
  42.         protected Class<?> findClass(String name) throws ClassNotFoundException {
  43.                 byte[] data=loadClassData(name);
  44.                 return defineClass(data, 0, data.length);
  45.         }
  46.        
  47.         //将class文件转化为byte[]
  48.         private byte[] loadClassData(String name) {
  49.                 //获取被加载类的完整路径
  50.                 String fileName=name.replace('.', '/');
  51.                 String filePath=path+fileName+".class";
  52.                
  53.                 /*通过BufferedInputStream读取目标class文件,
  54.                  * ByteArrayOutputStream将读取的文件转化为byte[]
  55.                  */
  56.                 BufferedInputStream in=null;
  57.                 ByteArrayOutputStream out=null;
  58.                 byte[] data=null;
  59.                 try {
  60.                         in=new BufferedInputStream(new FileInputStream(filePath));
  61.                         out=new ByteArrayOutputStream();
  62.                         byte[] buf=new byte[1024];
  63.                         int len=0;
  64.                         while ((len=in.read(buf))!=-1) {
  65.                                 out.write(buf,0,len);               
  66.                         }
  67.                         data=out.toByteArray();                       
  68.                 } catch (FileNotFoundException e) {
  69.                         e.printStackTrace();
  70.                 } catch (IOException e) {
  71.                         e.printStackTrace();
  72.                 }finally{ //关闭流
  73.                         if(in!=null)
  74.                                 try {
  75.                                         in.close();
  76.                                 } catch (IOException e) {
  77.                                         e.printStackTrace();
  78.                                 }finally{
  79.                                         if(out!=null)
  80.                                                 try {
  81.                                                         out.close();
  82.                                                 } catch (IOException e) {
  83.                                                         e.printStackTrace();
  84.                                                 }
  85.                                 }
  86.                 }
  87.                 return data;
  88.         }
  89.        
  90.         //重写toString方法
  91.         @Override
  92.         public String toString() {
  93.                 return this.name;
  94.         }
  95.        
  96.         //测试
  97.         public static void main(String[] args) throws Exception{
  98.                 MyClassLoader mcl=new MyClassLoader("myClassLoader");
  99.                 mcl.setPath("d:/");
  100.                 Class clazz=mcl.loadClass("com.cn.brainfreeze.Simple");
  101.                 Object simple=clazz.newInstance();
  102.                 Method function=clazz.getMethod("function");       
  103.                 function.invoke(simple);
  104.         }
  105. }
复制代码
回复 使用道具 举报

可以:
  1. package com.itheima;

  2. import java.io.BufferedInputStream;
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.File;
  5. import java.io.FileInputStream;
  6. import java.io.IOException;
  7. import java.io.InputStream;

  8. public class ClassLoaderTest {       

  9.         public static void main(String[] args)throws Exception {
  10.                 String loadDir = "";//可以加载其他文件夹的类文件,但下边的代码需要修改,且只能执行类文件的父类的方法
  11.                 String loadClazz = "com.itheima.ClassLoaderAttachment";
  12.                 Class clazz = new MyClassLoader(loadDir).loadClass(loadClazz);               
  13.                 ClassLoaderAttachment cla = (ClassLoaderAttachment)clazz.newInstance().getClass().getConstructor().newInstance();
  14.                 System.out.println(cla.toString());
  15.                 cla.fun();
  16.         }
  17. }

  18. class MyClassLoader extends ClassLoader{       

  19.     private String loadDir;  
  20.     private final String fileType = ".class";

  21.         public MyClassLoader() {
  22.         }
  23.        
  24.         public MyClassLoader(String loadDir) {
  25.                 this.loadDir = loadDir;
  26.         }
  27.        
  28.         protected Class<?> findClass(String name) {
  29.                         byte[] bytes = this.loadClassData(name);
  30.                         return defineClass(null, bytes, 0, bytes.length);
  31.         }       
  32.                
  33.         private byte[] loadClassData(String name) {  
  34.         InputStream in = null;  
  35.         byte[] data = null;  
  36.         ByteArrayOutputStream baos = null;  
  37.   
  38.         try {  
  39.             name = name.replace(".", "\\");  
  40.             in = new BufferedInputStream(new FileInputStream(new File(loadDir + name + fileType)));  
  41.             baos = new ByteArrayOutputStream();  
  42.             int ch = 0;  
  43.             while (-1 != (ch = in.read())) {  
  44.                 baos.write(ch);  
  45.             }  
  46.             data = baos.toByteArray();  
  47.         } catch (Exception e) {  
  48.   
  49.             e.printStackTrace();  
  50.         } finally {  
  51.             try {  
  52.                 in.close();  
  53.             } catch (IOException e1) {  
  54.                 e1.printStackTrace();  
  55.             } finally {  
  56.                 try {  
  57.                     baos.close();  
  58.                 } catch (IOException e2) {  
  59.                     e2.printStackTrace();  
  60.                 }  
  61.             }  
  62.         }  
  63.         return data;  
  64.     }

  65. }
复制代码
回复 使用道具 举报

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
您需要登录后才可以回帖 登录 | 加入黑马