Java探索之——Class字节码与ClassLoader(一)

首先定义自己的ClassLoader,可以加载磁盘上的.class文件:

 1 public class MyClassLoader extends ClassLoader{
 2     private String rootDir = ".";
 3     
 4     public MyClassLoader(String rootDir){
 5         this.rootDir = rootDir;
 6     }
 7     
 8     @Override
 9     public Class<?> findClass(String name)throws ClassNotFoundException{
10         byte[] bytes = readClassFile(name);
11         if(bytes!=null){
12             return defineClass(name, bytes, 0, bytes.length);
13         }else{
14             throw new ClassNotFoundException();
15         }
16     }
17     
18     private byte[] readClassFile(String name){
19         try {
20             File file = new File(rootDir+File.separatorChar+name+".class");
21             InputStream input = new FileInputStream(file);
22             byte[] buffer = new byte[4096];
23             ByteArrayOutputStream baos = new ByteArrayOutputStream();
24             int num = 0;
25             while((num = input.read(buffer))!=-1){
26                 baos.write(buffer, 0, num);
27             }
28             input.close();
29             return baos.toByteArray();
30         } catch (Exception e) {
31             e.printStackTrace();
32         }
33         return null;
34         
35     }
36 }

定义自己的JavaFileObject:

 1 public class MyJavaFileObject extends SimpleJavaFileObject{
 2     private String content;
 3     
 4     protected MyJavaFileObject(String name, String content) {
 5         super(URI.create("string:///"+name.replace(".", "/")+Kind.SOURCE.extension), Kind.SOURCE);
 6         this.content = content;
 7     }
 8     
 9     @Override
10     public CharSequence getCharContent(boolean ignoreEncodingErrors){
11         return content;
12     }
13     
14 }

 

再定义自己的编译器:

View Code
 1 /**
 2  * 自定义编译器
 3  * 
 4  * @author rui.chen
 5  * 
 6  */
 7 public class MyCompiler {
 8 
 9     /**
10      * 将输入的java源代码编译为二进制字节码
11      * @param className 类名
12      * @param source 类的实现java代码
13      * @return 是否编译成功
14      */
15     public boolean compile(String className, String source) {
16         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
17         StandardJavaFileManager fileManager = compiler.getStandardFileManager(
18                 null, null, null);
19         MyJavaFileObject obj = new MyJavaFileObject(className, source);
20         CompilationTask task = compiler.getTask(null, fileManager, null, null,
21                 null, Arrays.asList(obj));
22         return task.call();
23     }
24 
25     /**
26      * 通过反射加载类及调用类中的方法
27      * @param className 类名
28      * @param methodName 方法名
29      * @param types 参数类型
30      * @param args 方法参数数组
31      * @return 方法返回值
32      */
33     public Object invoke(String className, String methodName, Class<?>[] types, Object[] args) {
34         try {
35             ClassLoader loader = new MyClassLoader(".");
36             Class<?> clazz = loader.loadClass(className);
37             Method method = clazz.getMethod(methodName, types);
38             Object result = method.invoke(clazz.newInstance(), args);
39             return result;
40         } catch (Exception e) {
41             e.printStackTrace();
42         }
43         return null;
44 
45     }
46 }

最后上测试代码,实现一个简单的打印方法sayHello:

 1 public class CompilerTest {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         MyCompiler compiler = new MyCompiler();
 8         String source = "public class SaySomething {public void saySomething(String sth){System.out.println(sth);}}";
 9         compiler.compile("SaySomething", source);
10         compiler.invoke("SaySomething", "saySomething", new Class[]{String.class}, new String[]{"hello!"});
11     }
12 
13 }

参考资料:

java深度历险——成富;

深入探讨java类加载器

转载于:https://www.cnblogs.com/chrhust/archive/2013/05/09/3069375.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值