Class 类|类加载器|AOP|加密|JUnit

 
2006-8-25 学习总结
1、类 Class<T>
       Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(booleanbytecharshortintlongfloatdouble)和关键字 void 也表示为 Class 对象。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
以下示例使用 Class 对象来显示对象的类名:
    void printClassName(Object obj) 
    {
         System.out.println("The class of " + obj +" is " + obj.getClass().getName());
}
说明:类可以申明一个对象,即明一个具体的事物,平时申明对象的类也是一个事物,因此有一种类来申明这些类,这个类的名字就叫Class,他是所有类最高级别。
2、类加载器
Java编译后的java字节码class文件怎么加载到内存中的呢,其实他们是通过一个继承了ClassLoader类的java类加载到内存中的,然后这些加载类最后是通过一个本地c编写的加载器(Bootstrap)加载入内存中的,Bootstrap加载rt.jar这个包,而由这个加载器加载的调用.getClassLoader返回NULL。常用到的类加载器有AppClassLoader它用于加在classpath下的类,ExtClassLoader装<JAVA_HOME>/jre/lib/ext目录下的jar包,而AppClassLoader是ExtClassLoader的子类,所以AppClassLoader不能装载ExtClassLoader下的类。(注意:ClassLoader是委托父级类装载器加载的,一个类加载器在加载字节码时首先不是自己加载,而是找他的父加载器加载,如果父加载器可以加载那么就由父加载器加载,这就是junit的为什么不能放到<JAVA_HOME>/jre/lib/ext下的原因)。
Important: don't install the junit.jar into the extension directory of your JDK installation. If you do so the test class on the files system will not be found.(引用)
       类 ClassLoader:
              类加载器是负责加载类的对象。ClassLoader 类是一个抽象类。
ClassLoader 类使用委托模型来搜索类和资源。每个 ClassLoader 实例都有一个相关的父类加载器。需要查找类或资源时,ClassLoader 实例会在试图亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器。虚拟机的内置类加载器(称为 "bootstrap class loader")本身没有父类加载器,但是可以将它用作 ClassLoader 实例的父类加载器。
findClass:      protected Class<?> findClass(String name)
                                 throws ClassNotFoundException
loadClass:      protected Class<?> loadClass(String name, boolean resolve)
                                         throws ClassNotFoundException
使用指定的二进制名称来加载类。此方法的默认实现将按以下顺序搜索类:
1.     调用 findLoadedClass(String) 来检查是否已经加载类。
2.     在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。
3.     调用 findClass(String) 方法查找类。
如果使用上述步骤找到类,并且 resolve 标志为真,则此方法将在得到的 Class 对象上调用 resolveClass(Class) 方法。
鼓励用 ClassLoader 的子类重写 findClass(String),而不是使用此方法loadClass中也是调用findClass
4、AOP:
AOPOOP的延续,是Aspect Oriented Programming的缩写,意思是面向方面编程。面向对象将应用程序分解成各个层次的对象,而AOP将程序分解成各个方面 或者说 关注点这使得可以模块化诸如事务管理等这些横切多个对象的关注点。
5、Java单元测试——JUnit
JUnit就是一个测试Java程序的类,同时他提供了Java程序员一个写测试代码的规范。
JUnit是由 Erich Gamma Kent Beck 编写的一个回归测试框架(regression testing framework)。用于Java开发人员编写单元测试之用。
回归测试就是你不断地对所编写的代码进行测试:编写一些,测试一些,调试一些,然后循环这一过程。
所谓框架就是Erich Gamma Kent Beck 定下了一些条条框框,你编写的测试代码必须遵循这个条条框框:继承某个类,实现某个接口。其实也就是我们前面所说的规范。
6、注意:在抛出异常时,子类抛出异常只能是父类抛出异常的子类。
7、加密,自定义类装载器加载并运行
Tag:java 加密 (引用)         
以MyClassLoader.java为例,先加密Test.class文件,再用自定义类装载器加载并运行。
import java.io.*;
import java.lang.reflect.*;
public class MyClassLoader extends ClassLoader
{
       private String path = null;
       public MyClassLoader(String path) throws Exception//检查文件是否存在
       {
              File f = new File(path);
              if(!f.isDirectory())
              {
                     throw new RuntimeException(path + " is not a directory");
              }
              this.path = path;
       }
      
       public Class findClass(String name) //throws Exception //为什么不能抛出
       {
              try
              {
                     byte[] datas = loadClassData(name);
                     return defineClass(name, datas, 0, datas.length);
              }
              catch(Exception e)
              {
                     return null;
              }
       }
 
       private byte[] loadClassData(String name) throws Exception
       {
              File f = new File(path, name + ".class");//不用检查目录最后是否有目录分割符
              FileInputStream fis = new FileInputStream(f);
              ByteArrayOutputStream bas = new ByteArrayOutputStream();
              cypher(fis,bas);
              byte [] datas = bas.toByteArray();
              bas.close();
              fis.close();
              return datas;
       }
      
       public static void cypher(InputStream istream,OutputStream ostream) throws Exception
       {
              //下面这段代码可能遇到255的字节,当成byte就成了-1
              /*byte b = 0;
              while((b = (byte)istream.read()) != -1)
              {
                     ostream.write(b ^ 0xff);
              }*/
             
              int b = 0;
              while((b = istream.read()) != -1)
              {
                     ostream.write(((byte)b) ^ 0xff);
              }
       }
 
       public static void main(String [] args) throws Exception
       {
 
              //下面省略了错误检查
              if(!args[0].endsWith("class"))
              {
                     ClassLoader loader = new MyClassLoader(args[1]);
                     Class cls = loader.loadClass(args[0]);
                     //Method m = cls.getMethod("test",null);//在jdk1.5中报警告,为什么?
                     Method m = cls.getMethod("test");
                     //m.invoke(cls.newInstance(),null);
                     m.invoke(cls.newInstance());
                     //((Test)cls.newInstance()).test();
                     return;
              }
              else
              {           
                     FileInputStream fis = new FileInputStream(args[0]);         
                     File f = new File(args[1], new File(args[0]).getName());//不用检查目录最后是否有目录分割符
                     FileOutputStream fos = new FileOutputStream(f);            
                     cypher(fis,fos);
                     fis.close();
                     fos.close();
              }
       }
}
测试类:
       package cn.itcast;
public class Test extends java.util.Date
{
              public String toString()
              {
                     return "xixihehe";
              }
}
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章