黑马程序员:Java基础总结



类加载器

 
ASP.Net+Android+IO开发

.Net培训
、期待与您交流!





类加载器


Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader
类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是不是java类,这正是BootStrap。

类加载器是负责加载类的对象。ClassLoader 类是一个抽象类。如果给定类的二进制名称,那么类加载器会试图查找或生成构成类定义的数据。一般策略是将名称转换为某个文件名,然后从文件系统读取该名称的“类文件”。

每个 Class 对象都包含一个对定义它的 ClassLoader 的引用

数组类的 Class 对象不是由类加载器创建的,而是由 Java 运行时根据需要自动创建。数组类的类加载器由 Class.getClassLoader() 返回,该加载器与其元素类型的类加载器是相同的;如果该元素类型是基本类型,则该数组类没有类加载器。

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

类加载器通常由安全管理器使用,用于指示安全域。

ClassLoader 类使用委托模型来搜索类和资源。每个 ClassLoader 实例都有一个相关的父类加载器。需要查找类或资源时,ClassLoader 实例会在试图亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器。虚拟机的内置类加载器(称为 "bootstrap class loader")本身没有父类加载器,但是可以将它用作 ClassLoader 实例的父类加载器。

通常情况下,Java 虚拟机以与平台有关的方式,从本地文件系统中加载类。例如,在 UNIX 系统中,虚拟机从 CLASSPATH 环境变量定义的目录中加载类。

然而,有些类可能并非源自一个文件;它们可能源自其他来源(如网络),也可能是由应用程序构造的。defineClass 方法将一个 byte 数组转换为 Class 类的实例。这种新定义的类的实例可以使用 Class.newInstance 来创建。

类加载器所创建对象的方法和构造方法可以引用其他类。为了确定引用的类,Java 虚拟机将调用最初创建该类的类加载器的 loadClass 方法。

例如,应用程序可以创建一个网络类加载器,从服务器中下载类文件。示例代码如下所示:

   ClassLoader loader = new NetworkClassLoader(host, port);
Object main = loader.loadClass("Main", true).newInstance();
. . .

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

     class NetworkClassLoader extends ClassLoader {
String host;
int port; public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
} private byte[] loadClassData(String name) {
// load the class data from the connection
. . .
}
}

类加载器的委托机制
每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类装载器去加载类,这就是类加载器的委托模式。类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类装载器去进行真正的加载。当回退到最初的类装载器时,如果它自己也不能完成类的装载,那就应报告ClassNotFoundException异常。




            ClassLoader loader = Ts. 
class
.getClassLoader();
             
// 打印出当前的类装载器,及该类装载器的各级父类装载器
             
while 
(loader != 
null
) {
                  System. 
out
.println(loader.getClass().getName());
                  loader = loader.getParent();
            }
             
// 结果
             
// sun.misc.Launcher$AppClassLoader
             
// sun.misc.Launcher$ExtClassLoader
             
// null不是类,打印显示null




自定义的类加载器

自定义的类加载器的必须继承ClassLoader
loadClass方法与findClass方法
defineClass方法



ClassLoader 构造方法摘要
protected ClassLoader(ClassLoader parent)
          使用指定的、用于委托操作的父类加载器创建新的类加载器。
 Class<?> loadClass(String name)
          使用指定的二进制名称来加载类。
protected  Class<?> findLoadedClass(String name)
          如果 Java 虚拟机已将此加载器记录为具有给定二进制名称的某个类的启动加载器,则返回该二进制名称的类。
protected  Class<?> findClass(String name)
          使用指定的二进制名称查找类
protected  Class<?> defineClass(String name, byte[] b, int off, int len)
          将一个 byte 数组转换为 Class 类的实例。



import 
java.io.ByteArrayOutputStream;
import 
java.io.File;
import 
java.io.FileInputStream;

/**
 *
 * 一、ClassLoader加载类的顺序
 *  1.调用 findLoadedClass(String) 来检查是否已经加载类。
 *  2.在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。
 *  3.调用 findClass(String) 方法查找类。
 * 二、实现自己的类加载器
 *    1.用
FileInputStream
 
获取类的class文件的字节数组
 *    2.用
ByteArrayOutputStream
 ,
toByteArray()
将字节数组转换为Class类的实例
 *
 */
public 
class 
Ts {

       
public 
static 
void 
main(String[] args) 
throws 
InstantiationException, IllegalAccessException, ClassNotFoundException {
             
//新建一个类加载器
            MyClassLoader cl = 
new 
MyClassLoader(
"myClassLoader" 
);
             
//加载类,得到Class对象
            Class<?> clazz = cl.loadClass( 
"classloader.Animal"
);
             
//得到类的实例
            Animal animal=(Animal) clazz.newInstance();
            animal.say();
      }

}
class 
Animal{
       
public 
void 
say(){
            System. 
out
.println(
"hello world!" 
);
      }
}
class 
MyClassLoader 
extends 
ClassLoader {
       
//类加载器的名称
       
private 
String 
name
;
       
//类存放的路径
       
private 
String 
path 

"E:\\workspace\\Algorithm\\src"
;

      MyClassLoader(String name) {
             
this
.
name 
= name;
      }
      
      MyClassLoader(ClassLoader parent, String name) {
             
super
(parent);
             
this
.
name 
= name;
      }
       
/**
       * 重写findClass方法
       */
       
@Override
       
public 
Class<?> findClass(String name) {
             
byte
[] data = loadClassData(name);
             
return 
this 
.defineClass(name, data, 0, data.
length
);
      }
       
public 
byte
[] loadClassData(String name) {
             
try 
{
                  name = name.replace( 
"."

"//" 
);
                  FileInputStream is = 
new 
FileInputStream( 
new 
File(
path 
+ name + 
".class" 
));
                  ByteArrayOutputStream baos = 
new 
ByteArrayOutputStream();
                   
int 
b = 0;
                   
while 
((b = is.read()) != -1) {
                        baos.write(b);
                  }
                   
return 
baos.toByteArray();
            } 
catch 
(Exception e) {
                  e.printStackTrace();
            }
             
return 
null
;
      }

}




 
ASP.Net+Android+IO开发

.Net培训
、期待与您交流!

黑马程序员:Java基础总结----类加载器的更多相关文章

  1. 黑马程序员Java基础班+就业班课程笔记全发布(持续更新)

    正在黑马学习,整理了一些课程知识点和比较重要的内容分享给大家,也是给自己拓宽一些视野,仅供大家交流学习,大家有什么更好的内容可以发给我 ,现有黑马教程2000G  QQ 1481135711 这是我总 ...

  2. 黑马程序员----java基础笔记中(毕向东)

    <p>------<a href="http://www.itheima.com" target="blank">Java培训.Andr ...

  3. 黑马程序员----java基础笔记上(毕向东)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 笔记一共记录了毕向东的java基础的25天课程,分上.中.下 本片为上篇,涵盖前10天课程 1. ...

  4. 黑马程序员——JAVA基础之泛型和通配符

    ------- android培训.java培训.期待与您交流! ---------- 泛型:            JDK1.5版本以后出现新特性.用于解决安全问题,是一个类型安全机制. 泛型好处: ...

  5. 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象

    ------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...

  6. 黑马程序员——JAVA基础之语法、命名规则

    ------- android培训.java培训.期待与您交流! ---------- 1.java语言组成:关键字,标识符,注释,常量和变量,运算符,语句,函数,数组. 2.java关键字:被Jav ...

  7. 黑马程序员——JAVA基础之简述设计模式

    ------- android培训.java培训.期待与您交流! ---------- 设计模式(Design Patterns) 设计模式(Design pattern)是一套被反复使用.多数人知晓 ...

  8. 黑马程序员——JAVA基础之反射

      ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! -------     Java 反射是Java语言的一个很重要的特征,它使得Java具体了"动态 ...

  9. 黑马程序员——JAVA基础之GUI

    -----Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- GUI(图形用户界面)  GUI •  Graphical User Interface(图形用 ...

  10. 黑马程序员——JAVA基础之File类,递归,打印流,合并切割流

    ------- android培训.java培训.期待与您交流! ---------- File类 用来将文件或者文件夹封装成对象 方便对文件与文件夹的属性信息进行操作. File对象可以作为参数传递 ...

随机推荐

  1. ASP.NET 4.5 Bundle组件(捆绑、缩小静态文件)

    阅读目录: 1.开篇介绍 2.System.Web.Optimization 组件 3.System.Web.Optimization 组件基本原理 4.扩展自定义类型静态文件 1]开篇介绍 这篇文章 ...

  2. Study notes for B-tree and R-tree

    B-tree B-tree is a tree data structure that keeps data sorted and allows searches, sequential access ...

  3. TraceView总结

    一.TraceView简单介绍 TraceView是AndroidSDK里面自带的工具,用于对Android的应用程序以及Framework层的代码进行性能分析. TraceView是图形化的工具,终 ...

  4. mysql学习之中的一个:mysql安装

    我用的时mac系统,本来想在mac系统上装一个,可是发现mac系统始终无法用password登入到本机server,很奇怪的问题(在stackflow上看了些回复,也没有找到原因),最后仅仅好装到虚拟 ...

  5. Windows Azure入门教学系列 (三):创建第一个Worker Role程序

    在开始本教学之前,请确保你从Windows Azure 平台下载下载并安装了最新的Windows Azure开发工具.本教学使用Visual Studio 2010作为开发工具. 步骤一:创建解决方案 ...

  6. 基于visual Studio2013解决C语言竞赛题之1068指针数组

        题目 解决代码及点评 /* 68. 在主函数中输入10个不等长的字符串,用另一函数对它们排序. 然后在主函数中输出这10个已排好序的字符串,用指针数组完成. */ #inclu ...

  7. boost asio io_service学习笔记

    构造函数 构造函数的主要动作就是调用CreateIoCompletionPort创建了一个初始iocp. Dispatch和post的区别 Post一定是PostQueuedCompletionSta ...

  8. 52. 模版和设计元素——Lotus Notes的代码重用

    不论是理论上还是实用上,代码重用都是编程的一个重要议题.可以从两个角度来讨论代码重用. 一是逻辑上代码以怎样的方式被重用.既可以通过面向对象的思想普及以来耳熟能详的继承的方式.比如先建了一个车的基类, ...

  9. appium 真机测试问题 出现 instruments crashed on startup

    1.appium 真机测试的时候 instruments crashed on startup,必须在真机上打开UI Automation 在设置里: Developer->Enable UI ...

  10. Delphi 能不能从Ring 3进入Ring 0

    我发现了一篇发表在1999.11.29   b13版的     <令win32应用程序跳入系统层>东南大学   卢威   luwei@126.com     是用vc++嵌汇编做的,    ...