posts - 14,  comments - 37,  trackbacks - 0
JavaClassLoaderPackage机制介绍了ClassLoader的委派机制,它是把装载的任务传递给上级的装载器的,依次类推,直到启动类装载器(没有上级类装载器)。如果启动类装载器能够装载这个类,那么它会首先装载。如果不能,则往下传递。其实这引出一个运行时包的概念。不同装载器装载的类,即使包名相同也不能互相访问。这样保证了核心类库不被破坏。(by juxtapose)

本文将讲述如何扩展ClassLoader类实现一个自己的类装载器,每个Class对象都有一个引用指向装载他的ClassLoader,你可以通过public ClassLoader getClassLoader()方法得到它。为了创建自己的类装载器我们应该扩展ClassLoader类,这是一个抽象类。我们目的是从本地文件系统使用我们实现的类装载器装载一个类。我们创建一个FileClassLoader extends ClassLoader。我们需要覆盖ClassLoader中的
findClass(String name)
方法,这个方法通过类的名字而得到一个Class对象。

1public Class findClass(String name)
2{
3byte[] data = loadClassData(name);
4return defineClass(name, data, 0, data.length);
5}

6


我们还应该提供一个方法loadClassData(String name),通过类的名称返回class文件的字节数组。然后使用ClassLoader提供的defineClass()方法我们就可以返回Class对象了。

 1public byte[] loadClassData(String name)
 2{
 3FileInputStream fis = null;
 4byte[] data = null;
 5try
 6{
 7fis = new FileInputStream(new File(drive + name + fileType));
 8ByteArrayOutputStream baos = new ByteArrayOutputStream();
 9int ch = 0;
10while ((ch = fis.read()) != -1)
11{
12baos.write(ch);
13
14}

15data = baos.toByteArray();
16}
 catch (IOException e)
17{
18e.printStackTrace();
19}

20
21return data;
22}

23


这里我们是从D盘装载一个类。

下面我们提供一个类public class MyApp{},类中没有定义任何方法和变量,下面我们编译MyApp.java得到MyApp.class,然后把文件放在D盘的根目录。为了证明MyApp.class是被我们定义的classloader装载的,我们在FileClassLoadermain()方法中打印出装载MyApp.class的类装载器的名称。

 1public static void main(String[] args) throws Exception
 2{
 3FileClassLoader loader = new FileClassLoader();
 4Class objClass = loader.loadClass("MyApp"true);
 5Object obj = objClass.newInstance();
 6System.out.println(objClass.getName());
 7System.out.println(objClass.getClassLoader());
 8
 9
10}

11


编译FileClassLoader
javac FileClassLoader.java
然后运行java FileClassLoader 可以看到输出结果为

MyApp
FileClassLoader@1a5ab41

如果你把MyApp.class放入到你程序的所在目录会出现什么情况呢?读者自己实践一下吧!

结果为:MyApp

sun.misc.Launcher$AppClassLoader@92e78c

下面给出FileClassLoader的源代码。/*

  1* Created on 2005-7-27
  2
  3*
  4
  5* To change the template for this generated file go to
  6
  7* Window>Preferences>Java>Code Generation>Code and Comments
  8
  9*/
 10
 11
 12/**
 13
 14@author liuxiang
 15
 16*
 17
 18* To change the template for this generated type comment go to
 19
 20* Window>Preferences>Java>Code Generation>Code and Comments
 21
 22*/

 23
 24import java.io.ByteArrayOutputStream;
 25
 26import java.io.File;
 27
 28import java.io.FileInputStream;
 29
 30import java.io.IOException;
 31
 32public class FileClassLoader extends ClassLoader
 33
 34{
 35
 36public static final String drive = "d:/";
 37
 38public static final String fileType = ".class";
 39
 40
 41public FileClassLoader() {
 42
 43super();
 44
 45
 46}

 47
 48
 49public FileClassLoader(ClassLoader arg0) {
 50
 51super(arg0);
 52
 53}

 54
 55
 56public Class findClass(String name)
 57
 58{
 59
 60byte[] data = loadClassData(name);
 61
 62/*
 63
 64* Converts an array of bytes into an instance of class Class. 
 65
 66* Before the Class can be used it must be resolved. 
 67
 68
 69
 70* This method assigns a default ProtectionDomain to the newly 
 71
 72* defined class. The ProtectionDomain contains the set of 
 73
 74* permissions granted when a call to Policy.getPolicy().getPermissions() 
 75
 76* is made with a code source of null,null. The default domain 
 77
 78* is created on the first invocation of defineClass, and re-used 
 79
 80* on subsequent calls. 
 81
 82* To assign a specific ProtectionDomain to the class, use the 
 83
 84* defineClass method that takes a ProtectionDomain as one of 
 85
 86* its arguments. 
 87
 88*/

 89
 90/*
 91
 92* 该方法接受由原始字节组成的数组并把它转化成class对象
 93
 94* 原始字节包含从文件系统或网络装入的data
 95
 96* defineClass管理JVM中许多复杂、神秘和依赖于实现的方面————
 97
 98* ————它把字节码分析成运行时数据结构、校验有效性等。
 99
100*/

101
102return defineClass(name, data, 0, data.length);
103
104}

105
106
107/*
108
109* 将对应的Class文件读为byte[]
110
111*/

112
113public byte[] loadClassData(String name)
114
115{
116
117FileInputStream fis = null;
118
119byte[] data = null;
120
121try
122
123{
124
125//装载d:根目录下面的.class文件到data中
126
127fis = new FileInputStream(new File(drive + name + fileType));
128
129ByteArrayOutputStream baos = new ByteArrayOutputStream();
130
131int ch = 0;
132
133while ((ch = fis.read()) != -1)
134
135{
136
137baos.write(ch);
138
139
140}

141
142data = baos.toByteArray();
143
144}
 catch (IOException e)
145
146{
147
148e.printStackTrace();
149
150}

151
152
153return data;
154
155}
 
156
157
158public static void main(String[] args) throws Exception
159
160{
161
162FileClassLoader loader = new FileClassLoader();
163
164//装载类MyApp
165
166Class objClass = loader.loadClass("MyApp"true);
167
168//生成MyApp的一个实例
169
170Object obj = objClass.newInstance();
171
172//获得类的名称
173
174System.out.println(objClass.getName());
175
176//获得类的装载器的名称
177
178System.out.println(objClass.getClassLoader()); 
179
180}

181
182}

183
posted on 2007-06-26 14:27 冰封的爱 阅读(236) 评论(0)  编辑  收藏 所属分类: 技术

只有注册用户登录后才能发表评论。


网站导航:
 
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用链接

留言簿(3)

随笔档案

文章分类

文章档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜