做自己的类加载器

虚拟机的核心是通过类加载器来加载.class文件,然后进行相应的解析执行。那么我们可以自己做类加载器,手动加载需要的.class以进行解析执行,从而扩展虚拟机的功能。

以下内容摘自API文档:

应用程序需要实现 ClassLoader 的子类,以扩展 Java 虚拟机动态加载类的方式。

网络类加载器子类必须定义方法 findClass 和 loadClassData,以实现从网络加载类。下载组成该类的字节后,它应该使用方法 defineClass 来创建类实例。

代码示例:
自己的类加载器 MyClassLoader

package cn.hncu;import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;import org.junit.Test;public class MyClassLoader extends ClassLoader{public Class<?> findClass(String name){//name = "e:\\cn\\hncu\\Person.class"Class c = null;FileInputStream in;byte[] b=null;//通过IO或网络把字节码数据读取到buf[]当中。进一步地,//如果我们自己熟悉字节码的生成格式,那么也可自己用程序生成。//本例,我们是把硬盘中的一个外部字节码文件的数据读取到buf[]当中//1try {in = new FileInputStream(name);byte[] buf = new byte[1024]; ByteArrayOutputStream baos = new ByteArrayOutputStream();//字节流int len=0;while((len=in.read(buf))!=-1){baos.write(buf, 0, len);}in.close();baos.close();b = baos.toByteArray();//2 ---1-2这里可以抽取出来写一个loadClassData方法} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}c = defineClass("cn.hncu.Person", b, 0, b.length);return c;}@Testpublic void testClassData() throws ReflectiveOperationException{String className="cn.hncu.Person";//用Java的类加载器加载一个Class c = Class.forName(className);Object obj = c.newInstance();System.out.println(obj);System.out.println((Person)obj);System.out.println("-------------------");className = "e:\\cn\\hncu\\Person.class";Class c2 = findClass(className);Object obj2 = c2.newInstance();System.out.println(obj2);System.out.println((Person)obj2);//这句是有问题的//※不同类加载器加载的对象是无法强转---可以理解是不同的生存空间//Person p2 = (Person) obj2;//会挂的。//因为obj2的生存空间是MyClassLoader,而Person的生成空间是AppClassLoader//System.out.println(p2);}}

测试结果:

看,最后那句不能输出吧。
因为不是一个类加载器的。

作自己的测试工具MyJUnit
(注解与反射共同使用的案例 )

相关说明:

1)JUnit用的是@Test注解,我们用@MyTest注解。

2)JUnit已经嵌入到MyEclipse当中,我们自己的MyJUnit只要能独立运行就可以(不嵌入),同时这样我们也不方便在MyJUnit中以参数方式接收到被测试类的类名与方法名,只能以键盘输入的方式接收。

3)JUnit能实现指定单个方法来调用执行,由于不能利用MyEclipse传参,因此我们在MyJUnit程序中遍历所有的方法并通过判断是否声明@MyTest注解来决定是否调用执行该方法。

下面实现了运行任意目录下的实现了@MyTest注解的方法:
需要输入绝对路径名和类的完整名字。

注解:@MyTest

package cn.hncu.myJunit;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)//运行时也存在,必须要加这个
@Target (ElementType.METHOD)//限制注解只能加在方法上
public @interface MyTest {}

测试类:TestPerson

package cn.hncu.myJunit;
/*** 测试用的* @author 陈浩翔** @version 1.0  2016-5-6*/
public class TestPerson {public void run1(){System.out.println("run1...");}@MyTestpublic void run2(){System.out.println("run2...");}public void run3(){System.out.println("run3...");}@MyTestpublic void run4(){System.out.println("run4...");}public void run5(){System.out.println("run5...");}}

MyClassLoader类:自己写的类加载器

package cn.hncu.myJunit;import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;/*** 自己写的类加载器* @author 陈浩翔** @version 1.0  2016-5-6*/
public class MyClassLoader extends ClassLoader{//我把它分成2个方法写了。public  Class<?> findClass(String name, String className) {try {byte b[] = loadClassData(name);Class c = defineClass(className, b, 0, b.length);return c;} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}private static byte[] loadClassData(String name) throws IOException {byte buf[] = new byte[1024];FileInputStream in = new FileInputStream(name);ByteArrayOutputStream out = new ByteArrayOutputStream();int len=0;while((len=in.read(buf))!=-1){out.write(buf, 0, len);}in.close();out.close();byte b[] = out.toByteArray();return b;}
}

main方法类:

package cn.hncu.myJunit;import java.lang.reflect.Method;
import java.util.Scanner;import cn.hncu.myJunit.MyClassLoader;/*** @author 陈浩翔* @version 1.0  2016-5-6*/
public class MyJunit {public static void main(String[] args) throws ReflectiveOperationException {Scanner sc = new Scanner(System.in);System.out.println("请输入需要运行的类的绝对路径(路径中不能有空格,需要类的.class文件):");String name = sc.next();System.out.println("请输入类的名称(包含包名):");String className = sc.next();Class c = (new MyClassLoader()).findClass(name, className);//获得那个类了。//那个类必须要有空参构造方法Object obj = c.newInstance();//获得这个类所有声明的方法,包括私有的Method ms[] = c.getDeclaredMethods();for(Method m:ms){if(m.isAnnotationPresent(MyTest.class)){m.invoke(obj, null);}}}
}

运行测试结果:

现在我把class文件移动到D盘了。

再看运行结果:

这个可以有很多改进的地方,就比如每次输入路径都很麻烦,
我们可以做一个图形界面,让我们自己选择。
这样就方便多了。

Java---注解、类加载器-加强-实现运行任意目录下class中加了@MyTest的空参方法相关推荐

  1. 【JAVA开发技术进阶】 Java实现运行任意目录下class中加了@MyTest的空参方法(实现图形界面)

    说明: 因为上个代码,总是要输入完整的绝对路径,比较麻烦,于是,就写了这个小程序,直接进入文件对话框选择需要运行的class文件. 只需要提前输入完整的类名. 注意:加的MyTest必须打个包,加上: ...

  2. Java---实现运行任意目录下class中加了@MyTest的空参方法(实现图形界面)

    说明: 因为上个代码,总是要输入完整的绝对路径,比较麻烦,于是,就写了这个小程序,直接进入文件对话框选择需要运行的class文件. 只需要提前输入完整的类名. 注意:加的MyTest必须打个包,加上: ...

  3. JVM00_面试官对类加载器子系统、运行时数据区、内存分布、执行引擎的灵虚拷问,你能坚持到第几问?

    因为热爱所以坚持,因为热爱所以等待.熬过漫长无戏可演的日子,终于换来了人生的春天.他逐渐被人熟知,被人喜爱 三年前,在苏州园区某个国企面试,第一道题目便是:JVM是什么吗?然后就是拿着笔试题目被面试官 ...

  4. OSGi 规范和框架 OSGi框架类加载机制 Java默认类加载器机制和OSGI类加载器机制比较

    一.OSGi 规范 OSGi(Open Service Gateway Initiative) 技术是 Java 动态化模块化系统的一系列规范.OSGi 一方面指维护 OSGi 规范的 OSGi Al ...

  5. 反射-注解-类加载器知识

    反射知识 概念 反射机制就是将类的各个组成部分(属性,方法,构造器)封装为其他对象 Class Method Constructor 相关的核心类 java.lang.Class(这个就是类的对象) ...

  6. java安全——类加载器+字节码校验+安全管理器与访问权限

    [0]README 0.1)本文文字描述转自 core java volume 2,旨在学习 java安全 的相关知识: [1]类加载器 1)java 技术提供了以下3种确保安全的机制(mechani ...

  7. java的双亲委派_深入理解Java的类加载器及双亲委派机制

    当我们在写完一个Java文件的时候,编译器会将.java文件编译成.class文件,然后当程序运行时,JVM首先会找到main方法所在类,并将main所在类的class文件字节码读到内存中,转换成JV ...

  8. java基础类加载器_Java基础之类加载器

    1. 什么是类加载器? 加载类的工具. 2. Java虚拟机中可以安装多个类加载器,系统默认三个主要的类加载器,每个类负责加载特定位置的类: BootStrap,ExtClassLoader,AppC ...

  9. java的类加载器以及如何自定义类加载器

    ClassLoader作用 类加载流程的"加载"阶段是由类加载器完成的. 类加载器结构 结构:BootstrapClassLoader(祖父)–>ExtClassLoader ...

最新文章

  1. python内置函数:iter、enumerate和next
  2. 《java编程思想》学习笔记——内部类五
  3. 更改oracle 端口,Oracle数据库11G R2 修改服务端口
  4. PHP 如何准确取得服务器地址IP[非代理]
  5. 【转】OData – the best way to REST–实例讲解ASP.NET WebAPI OData (V4) Service Client
  6. excel 2007 vba与宏完全剖析_Excel宏VBA小技巧系列 | 分段加合
  7. LeetCode 647. 回文子串(DP/中心扩展)
  8. photoshop切图
  9. 新员工入职自动加入所在部门的邮件组。
  10. 使用srvany.exe把程序安装成windows服务的方法
  11. 和菜鸟一起深入学习国嵌实验之vim常用命令
  12. Log4j框架配置文件log4j.properties配置使用详解
  13. ActivityGroup的使用
  14. 7-6 输出上三角队形
  15. 软考信息系统项目管理师知识点总结(高项十大管理案例分析作文)
  16. 桌面图标拖不动怎么办?
  17. JavaScript模块机制
  18. 联想7400pro打印有横黑道
  19. Linux UVC driver 独立交叉编译记录
  20. 【Qt】 Fractal Designer 5.3 - Help(中文版)

热门文章

  1. (学习)基于STM32的PWM控制直流电机转速(CubeMX+HAL库)
  2. 浅谈 long long 和 int 的区别
  3. 程序员锁死服务器搞垮上家公司后,下家公司说不敢惹不敢惹!
  4. Flink 核心技术浅析(整理版)
  5. 1553B总线系统如何搭建?
  6. 新致新知 | 共享.确权.开放式 知识图谱平台
  7. java如何将war包打成ear包_关于war包 jar包 ear包 及打包方法
  8. 云服务器哪家性价比高?阿里云ECS服务器最便宜102元/年
  9. IDEA配置.gitignore
  10. 学习 MongoDB 一篇文章就够了(珍藏版)