类加载器的深入与应用

本文深入探讨了Java类加载器的工作原理,包括BootStrap、ExtClassLoader和AppClassLoader的作用及其实现方式。此外,还详细介绍了自定义类加载器的设计方法,并通过示例展示了如何实现对class文件的加密。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.类加载器及其委托机制的深入分析

概念:java虚拟机将一个类加载到内存所需要的类就叫类加载器;从classpath 加载.class文件到内存生成字节码。
2java虚拟机可以安装多个类加载器, 系统默认三个类加载器:BootStrap ExtClassLoader AppClassLoader;
Java 加载器也是java类, 但是BootStrap不是java类写,而是C++ 写的;
例子:

packageorg.nagi.base;

//测试类加载器
publicclass TestClassLoader {

   publicstaticvoid main(String[] args) {
      String name = TestClassLoader.class.getClassLoader().getClass().getName();
      System.out.println(name);
      //运行结果sun.misc.Launcher$AppClassLoader
   }
}

AppClassLoaderd加载ClassPacth 指定目录,ExtClassLoader加载JRE/lib/ext/*jar

BootStrap 加载JRE/lib/rt.jar 当我们在加载类的时候,系统默认是从当前的线程加载类,

这个我们也可以指定类加载器,在thread 方法中有setContextClassLoader()方法
void
setContextClassLoader(ClassLoader cl)
设置该线程的上下文 ClassLoader
当appClassLoader在加载时候,它会交给自己父类加载;这样可以避免各干个的,内存也不会出现的两份字节码。 这就是委托加载机制又叫双亲委派机制。

2.自定义类加载器的编写原理分析

自己编写类加载器:模块设计方法:
父类:classLoader()子类1:classLoader() 子类2 :classLoader
基础知识原理:
(1)自己定义加载器需要覆盖findClassLoader();这样在加载我们自己的类的时候不会交给双亲去处理。
(2)将class 文件变成了字节码,difineClass()方法,
(3)代码:

 public Class findClass(String name) {
       byte[] b = loadClassData(name);
       return defineClass(name, b, 0, b.length);
         }

代码:

importjava.io.ByteArrayOutputStream;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
import java.io.InputStream;
importjava.io.OutputStream;

publicclass MyClassLoaderextends ClassLoader{

   /**
    * @param args
    */
   publicstaticvoid main(String[] args)throws Exception {
      String srcPath = args[0];
      String destDir = args[1];
      FileInputStream fis = new FileInputStream(srcPath);
      String destFileName =srcPath.substring(srcPath.lastIndexOf('\\')+1);//得到了目标类
      String destPath = destDir + "\\" + destFileName;
      FileOutputStream fos = new FileOutputStream(destPath);
      cypher(fis,fos);
      fis.close();
      fos.close();
   }

   /**
    * 对字节码加密
    * @param ips
    * @param ops
    * @throws Exception
    */
   privatestaticvoid cypher(InputStream ips ,OutputStream ops)throws Exception{
      int b = -1;
      while((b=ips.read())!=-1){
        ops.write(b ^ 0xff);
      }
   }

   private StringclassDir;

   @Override
   protected Class<?> findClass(String name)throws ClassNotFoundException {
      StringclassFileName = classDir +"\\"  +name.substring(name.lastIndexOf('.')+1) +".class";
      try {
        FileInputStream fis = new FileInputStream(classFileName);
        ByteArrayOutputStream  bos = new ByteArrayOutputStream();
        cypher(fis,bos);
        fis.close();
        System.out.println("aaa");
        byte[] bytes = bos.toByteArray();
        returndefineClass(bytes, 0,bytes.length);//返回字节码
      } catch (Exception e) {
        e.printStackTrace();
      }
      returnnull;
   }

   public MyClassLoader(){

   }
   //实例化classDir
   public MyClassLoader(String classDir){
      this.classDir = classDir;
   }
}

调用自己定义好的类加载器:

Class clazz =new MyClassLoader("itcastlib").loadClass("cn.itcast.day2.ClassLoaderAttachment");
      Date d1 = (Date)clazz.newInstance();
      System.out.println(d1);

3.编写对class文件进行加密的工具类

     /**
    * 对字节码加密
    * @param ips
    * @param ops
    * @throws Exception
    */
private static void cypher(InputStream ips ,OutputStream ops)throws Exception{
      int b = -1;
      while((b=ips.read())!=-1){
        ops.write(b ^ 0xff);
      }
   }

**4.类加载器的一个高级问题的实验分析
编写一个类加载器,可以打印出自己类的加载器名称和父类的加载器名称,显示出加载的父子结构关系;**

建立一个Servlet
在doGet方法下打印出

ClassLoaderLoader =this.getClass().getClassLoader();
      while(Loader !=null){
        out.print(Loader.getParent());
      }

在Tomcat加载的时候,就显示出加载类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值